pyhttpcgi

Handles GET requests, based on http.server.
For /, tries to handle /index but falls back to a cached ./index.html file if this fails. For /path, tries to execute ./path, passing the query (?x=1&y=2) as environment variables (ARG_x=1 ARG_y=2).
If the path contains something except alphanumerics, underscore, dash, and (not leading) dot, or if the execution failed or returned nonzero, responds with http 400. Missing or duplicated query parameters, or ones with unsafe names (see path), are silently ignored.

Pass argument addr:port to one of
python3 pyhttpcgi.py
python3 -c "$(base64 -d <<< ZnJvbSBodHRwLnNlcnZlciBpbXBvcnQgQmFzZUhUVFBSZXF1ZXN0SGFuZGxlciwgSFRUUFNlcnZlcgpmcm9tIHVybGxpYi5wYXJzZSBpbXBvcnQgdXJsc3BsaXQsIHBhcnNlX3FzCmZyb20gc3VicHJvY2VzcyBpbXBvcnQgcnVuCmZyb20gc3lzIGltcG9ydCBhcmd2LCBleGl0CmZyb20gb3MgaW1wb3J0IGVudmlyb24KCmlmIGxlbihhcmd2KSA8PSAxOgoJcHJpbnQoIkFyZzogYWRkcjpwb3J0LCBvciBwb3J0IChsb2NhbGhvc3QpLCBvciA6cG9ydCAoYWxsIGludGVyZmFjZXMpIikKCWV4aXQoMCkKaWYgJzonIGluIGFyZ3ZbMV06CglBRERSID0gYXJndlsxXS5yc3BsaXQoJzonLCAxKQoJUE9SVCA9IGludChBRERSWzFdKQoJQUREUiA9IEFERFJbMF0KZWxzZToKCUFERFIgPSAnbG9jYWxob3N0JwoJUE9SVCA9IGludChhcmd2WzFdKQpwcmludChmJ0xpc3RlbmluZyBvbiB7QUREUiBvciAnKid9OntQT1JUfScpCgp0cnk6Cgl3aXRoIG9wZW4oJ2luZGV4Lmh0bWwnLCAncmInKSBhcyBmOgoJCUlYID0gZi5yZWFkKCkKZXhjZXB0OgoJSVggPSBOb25lCgpkZWYgYWxudW0odik6CglyZXR1cm4gYWxsKChjIGluICdhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OV8tLicgZm9yIGMgaW4gdikpIGFuZCBub3Qgdi5zdGFydHN3aXRoKCIuIikKCmNsYXNzIEhhbmRsZXIoQmFzZUhUVFBSZXF1ZXN0SGFuZGxlcik6CglkZWYgZG9fR0VUKHNlbGYpOgoJCXUgPSB1cmxzcGxpdChzZWxmLnBhdGgpCgkJcCA9IHUucGF0aAoJCWEgPSBwYXJzZV9xcyh1LnF1ZXJ5KQoJCWlmIHAuc3RhcnRzd2l0aCgnLycpOgoJCQlwID0gcFsxOl0KCQlpZiBub3QgYWxudW0ocCk6CgkJCXNlbGYuc2VuZF9yZXNwb25zZSg0MDApCgkJCXNlbGYuZW5kX2hlYWRlcnMoKQoJCQlyZXR1cm4KCQljdCA9IE5vbmUKCQlpZiBsZW4ocCkgPT0gMDoKCQkJcCA9ICdpbmRleCcKCQkJY3QgPSBJWAoJCXRyeToKCQkJZW52ID0gTm9uZQoJCQlpZiBsZW4oYSkgPiAwOgoJCQkJZW52ID0gZGljdChlbnZpcm9uKQoJCQkJZm9yIGsgaW4gYToKCQkJCQlpZiBhbG51bShrKSBhbmQgbGVuKGFba10pID09IDEgYW5kIGFsbnVtKGFba11bMF0pOgoJCQkJCQllbnZbZidBUkdfe2t9J10gPSBhW2tdWzBdCgkJCWMgPSBydW4oYXJncz1bZicuL3twfSddLCBlbnY9ZW52LCBjaGVjaz1UcnVlLCBjYXB0dXJlX291dHB1dD1UcnVlKQoJCQljdCA9IGMuc3Rkb3V0CgkJZXhjZXB0OgoJCQlwYXNzCgkJaWYgY3QgaXMgTm9uZSBhbmQgKElYIGlzIE5vbmUgb3IgcCAhPSAnaW5kZXgnKToKCQkJc2VsZi5zZW5kX3Jlc3BvbnNlKDQwMCkKCQkJc2VsZi5lbmRfaGVhZGVycygpCgkJCXJldHVybgoJCXNlbGYuc2VuZF9yZXNwb25zZSgyMDApCgkJc2VsZi5zZW5kX2hlYWRlcignQ29udGVudC10eXBlJywgJ3RleHQvaHRtbCcpCgkJc2VsZi5lbmRfaGVhZGVycygpCgkJc2VsZi53ZmlsZS53cml0ZShjdCkKCkhUVFBTZXJ2ZXIoKEFERFIsIFBPUlQpLCBIYW5kbGVyKS5zZXJ2ZV9mb3JldmVyKCkK)"
🢘 back⌂ home✉ contact