Skip to content

Instantly share code, notes, and snippets.

@dubiouscript
Created February 22, 2019 15:17
Show Gist options
  • Save dubiouscript/3b7daad8878fdd51b125732a66934740 to your computer and use it in GitHub Desktop.
Save dubiouscript/3b7daad8878fdd51b125732a66934740 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# HTTP web service implemented in socat + bash
# Usage: socat -T 1 -d -d tcp-l:8080,reuseaddr,fork,crlf exec:./server
# Purpose: Provide an HTTP server that displays the current server date,
# to validate the artifact structure and play with it.
# Note: socat crlf option is translating all our \n to \r\n on output.
http_version="1.0"
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"
[402]="Payment Required"
[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_headers() {
local h dt
printf -v dt "%(%c %Z)T" -1
local -a hdrs=(
"Date: ${dt}"
"Expires: ${dt}"
"Content-Type: text/plain"
"Server: hello-bash@${HOSTNAME}/0.0.1"
)
for h in "${hdrs[@]}"; do
echo "${h}"
done
}
function _send_body() {
echo "Yo yo yo!"
}
function _send_response() {
echo "HTTP/${http_version} ${1} ${_http_responses[${1}]}"
_send_headers
echo ""
_send_body
}
function _respond_with() {
if [ "$#" -ne 1 ]; then
>&2 "Error: Expected one argument for ${FUNCNAME}, received $#."
>&2 "Usage: ${0} CODE"
return 1
fi
_send_response "${1}"
}
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment