112 lines
2.4 KiB
Bash
Executable File
112 lines
2.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# A simple, configurable HTTP server written in bash.
|
|
#
|
|
# See LICENSE for licensing information.
|
|
#
|
|
# Original author: Avleen Vig, 2012
|
|
# Reworked by: Josh Cartwright, 2012
|
|
|
|
warn() { echo "WARNING: $@" >&2; }
|
|
|
|
recv() { echo "< $@" >&2; }
|
|
send() { echo "> $@" >&2;
|
|
printf '%s\r\n' "$*"; }
|
|
|
|
[[ $UID = 0 ]] && warn "It is not recommended to run bashttpd as root."
|
|
|
|
DATE=$(date +"%a, %d %b %Y %H:%M:%S %Z")
|
|
declare -a RESPONSE_HEADERS=(
|
|
"Date: $DATE"
|
|
"Expires: $DATE"
|
|
"Server: Slash Bin Slash Bash"
|
|
)
|
|
|
|
add_response_header() {
|
|
RESPONSE_HEADERS+=("$1: $2")
|
|
}
|
|
|
|
declare -a HTTP_RESPONSE=(
|
|
[200]="OK"
|
|
[400]="Bad Request"
|
|
[403]="Forbidden"
|
|
[404]="Not Found"
|
|
[405]="Method Not Allowed"
|
|
[500]="Internal Server Error"
|
|
)
|
|
|
|
send_response() {
|
|
local code=$1
|
|
send "HTTP/1.0 $1 ${HTTP_RESPONSE[$1]}"
|
|
for i in "${RESPONSE_HEADERS[@]}"; do
|
|
send "$i"
|
|
done
|
|
send
|
|
while read -r line; do
|
|
send "$line"
|
|
done
|
|
}
|
|
|
|
send_response_ok_exit() { send_response 200; exit 0; }
|
|
|
|
fail_with() {
|
|
send_response "$1" <<< "$1 ${HTTP_RESPONSE[$1]}"
|
|
exit 1
|
|
}
|
|
serve_static_string() {
|
|
add_response_header "Content-Type" "text/plain;charset=utf-8"
|
|
send_response_ok_exit <<< "$1"
|
|
}
|
|
|
|
where () {
|
|
h="$(dirname "$0")"
|
|
# If $h isnt absolute, prepend working dir
|
|
if [[ ! "${h:0:1}" = "/" ]] ; then
|
|
h="$(pwd)/$(dirname "$0")"
|
|
fi
|
|
h="$(realpath "$h")"
|
|
echo "$h"
|
|
}
|
|
|
|
main () {
|
|
# Request uri must be a relative path from the exercices/corriges directory
|
|
[ -x "$REQUEST_URI" ] || [ ! -d "$REQUEST_URI" ] || fail_with 404
|
|
here="$(where)"
|
|
path="$(realpath "$here/exercices/corriges/$REQUEST_URI")"
|
|
[[ "$path" = "$here"* ]] || fail_with 404
|
|
serve_static_string "$(basename "$path" | cut -d '.' -f 1) : $(bash "$path" 2>&1 && echo Ok || echo 'Non validé')"
|
|
}
|
|
|
|
# Request-Line HTTP RFC 2616 $5.1
|
|
read -r line || fail_with 400
|
|
|
|
# strip trailing CR if it exists
|
|
line=${line%%$'\r'}
|
|
recv "$line"
|
|
|
|
read -r REQUEST_METHOD REQUEST_URI REQUEST_HTTP_VERSION <<<"$line"
|
|
|
|
[ -n "$REQUEST_METHOD" ] && \
|
|
[ -n "$REQUEST_URI" ] && \
|
|
[ -n "$REQUEST_HTTP_VERSION" ] \
|
|
|| fail_with 400
|
|
|
|
# Only GET is supported at this time
|
|
[ "$REQUEST_METHOD" = "GET" ] || fail_with 405
|
|
|
|
declare -a REQUEST_HEADERS
|
|
|
|
while read -r line; do
|
|
line=${line%%$'\r'}
|
|
recv "$line"
|
|
|
|
# If we've reached the end of the headers, break.
|
|
[ -z "$line" ] && break
|
|
|
|
REQUEST_HEADERS+=("$line")
|
|
done
|
|
|
|
main
|
|
|
|
fail_with 500
|