-
-
Save mbbx6spp/0ba0406afe65db556eef to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash | |
# Purpose: Provide HTTP server that displays the current server date to | |
# validate the artifact structure and play with. | |
declare -a _http_responses=( | |
[200]="OK" | |
[201]="Created" | |
[202]="Accepted" | |
[204]="No Content" | |
[301]="Moved Permanently" | |
[302]="Found" | |
[307]="Temporary Redirect" | |
[400]="Bad Request" | |
[401]="Unauthorized" | |
[403]="Forbidden" | |
[404]="Not Found" | |
[405]="Method Not Allowed" | |
[500]="Internal Server Error" | |
[501]="Not Implemented Error" | |
[502]="Bad Gateway" | |
[503]="Temporarily Unavailable" | |
) | |
function _recv() { | |
echo "< $*" >&2 | |
} | |
function _send() { | |
printf '%s\r\n' "$*" | |
} | |
function _send_headers() { | |
local -r dt="$(date +"%a, %d %b %Y %H:%M:%S %Z")" | |
local -r hst="$(hostname -s)" | |
local -a hdrs=( | |
"Date: ${dt}" | |
"Expires: ${dt}" | |
"Content-Type: text/plain" | |
"Server: hello-bash@${hst}/0.0.1" | |
) | |
for h in "${hdrs[@]}"; do | |
_send "${h}" | |
done | |
} | |
function _send_body() { | |
_send "Yo yo yo!" | |
} | |
function _send_response() { | |
_send "${1}" | |
_send_headers | |
_send "" | |
_send_body | |
} | |
function _respond_with() { | |
if [ "$#" -ne 1 ]; then | |
>&2 "Error: Expected one argument for ${FUNCNAME}, received $#." | |
>&2 "Usage: ${0} CODE" | |
return 1 | |
fi | |
local -r code="${1}" | |
_send_response "${code} ${_http_responses[${code}]}" | |
} | |
function _parse_request() { | |
if [ "$#" -ne 1 ]; then | |
>&2 "Error: Expected one argument for ${FUNCNAME}, received $#." | |
>&2 "Usage: ${0} REQUEST_LINE" | |
return 1 | |
fi | |
local -r req="${1%%$'r'}" | |
read -r req_method req_uri req_http_ver <<<"${req}" | |
# Validate request (only support GET and / URI so far :) | |
if [ "${req_method}" = "GET" -a "${req_uri}" = "/" -a -n "${req_http_ver}" ]; then | |
_respond_with 200 | |
elif [ "${req_uri}" != "/" ]; then | |
_respond_with 404 | |
elif [ -z "${req_http_ver}" ]; then | |
_respond_with 400 | |
else | |
_respond_with 500 | |
fi | |
} | |
function _main() { | |
read -r line || _respond_with 400 | |
_parse_request "${line}" | |
} | |
if [ "${BASH_SOURCE[0]}" != "${0}" ]; then | |
export -f _respond_with | |
export -f _parse_request | |
else | |
set -eu | |
_main | |
fi |
You can eliminate 2 forks if you want. Bash has both date and hostname built-in.
Also if you take the care to make dt local, the so should h.
replace:
local -r dt="$(date +"%a, %d %b %Y %H:%M:%S %Z")"
local -r hst="$(hostname -s)"
...
"Server: hello-bash@${hst}/0.0.1"
with:
local h dt
printf -v dt "%(%a, %d %b %Y %H:%M:%S %Z)T" -1
...
"Server: hello-bash@${HOSTNAME}/0.0.1"
Erm, second thought, this is not a web service after all.
The output all ends up in the content and the headers are not treated as headers by real http clients.
try:
curl -D apache_headers.txt localhost >apache_content.txt
curl -D bash_headers.txt localhost:8080 >bash_content.txt
Perhaps somehow a newline is getting output before the headers, or perhaps it's something else entirely.
It's the missing HTTP/1.0
See the example here:
https://stuff.mit.edu/afs/sipb/machine/penguin-lust/src/socat-1.7.1.2/EXAMPLES
socat -T 1 -d -d tcp-l:10081,reuseaddr,fork,crlf system:"echo -e \"\\\"HTTP/1.0 200 OK\\\nDocumentType: text/html\\\n\\\n<html>date: \$\(date\)<br>server:\$SOCAT_SOCKADDR:\$SOCAT_SOCKPORT<br>client: \$SOCAT_PEERADDR:\$SOCAT_PEERPORT\\\n<pre>\\\"\"; cat; echo -e \"\\\"\\\n</pre></html>\\\"\""
That example is also using socat to convert LF to CRLF, so, if following that example, you wouldn't need _send(), just plain echo everywhere.
We don't need to use the system: option from that example, exec: is fine, since we are using a script in a file, not shell commands directly on the commandline.
Restored my version that went away when that account was deleted (I'm the "ghost" above)
https://gist.github.com/bkw777/e026f514306065e3d4e2c5b85e911838
I've repaired a significant oversight: https://gist.github.com/polynomial/9f62514de596ca96d0c3/revisions