emptyok_response() {( printf "HTTP/1.1 204 OK\r\n" printf 'Connection: close\r\n' printf 'Server: %s\r\n' "$Server" printf '\r\n' )} not_modifed_response() {( printf "HTTP/1.1 304 Not Modified\r\n" printf 'Connection: close\r\n' printf 'Server: %s\r\n' "$Server" printf '\r\n' )} delete_response() { jq -n -r \ --arg server "$Server" \ ' [ "HTTP/1.1 204 OK\r" , "Connection: close\r" , "Server: \($server)\r" , "\r" ][] ' } file_response() {( type=$(file -ib "$1") size=$(wc -c < "$1") jq -n -r \ --arg type "$type" \ --arg size "$size" \ --arg server "$Server" \ ' [ "HTTP/1.1 200 OK\r" , "Connection: close\r" , "Content-Length: \($size)\r" , "Content-Type: \($type)\r" , "Server: \($server)\r" , "\r" ][] ' cat "$1" )} read_uri() { jq -cn --arg uri "$1" ' $uri | capture("^((?[^:]*):)?(//(?[^/]*))?(?[^?#]*)([?](?[^#]*))?([#](?.*))?$") | . + { query: (.query | if . != null then split("&") | map(split("=") | {key:.[0],value:.[1]}) | from_entries else . end) } ' } uri=$(read_uri "$Request_URI") path=$(jq -nr --argjson uri "$uri" ' $uri.path | gsub("/+"; "/") ') case "$Method $path" in 'POST /'*|'PUT /'*) content=$(mktemp -t htgen.$$.content.XXXXXXXX) trap "rm $content >&2" EXIT head -c $req_content_length > $content item=$STATEDIR/items/$(echo "$path" | jq -rR @uri) mkdir -v -p $STATEDIR/items >&2 cp -v $content $item >&2 emptyok_response exit ;; 'GET /'*) item=$STATEDIR/items/$(echo "$path" | jq -rR @uri) if [ -e "$item" ]; then if [ -z ${req_if_modified_since+x} ]; then file_response "$item" exit else age_file=$(date +%s -r "$item") age_header=$(date +%s --date="$req_if_modified_since") if [ "$age_file" -lt "$age_header" ]; then not_modifed_response exit else file_response "$item" exit fi fi fi ;; 'DELETE /'*) item=$STATEDIR/items/$(echo "$path" | jq -rR @uri) if [ -e "$item" ]; then rm "$item" delete_response exit fi esac