I use python for serving my local static site development with this custom little bash wrapper script I wrote:
#!/usr/bin/env bash
set -e; [[ $TRACE ]] && set -x
port=8080
dir="."
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
echo "usage: http-server [PORT] [DIRECTORY]"
echo " PORT Port to listen on (default: 8080)"
echo " DIRECTORY Directory to serve (default: .)"
exit 0
fi
if [ -n "$1" ]; then
port=$1
fi
if [[ -n "$2" ]]; then
dir=$2
fi
python3 -m http.server --directory "$dir" --protocol HTTP/1.1 "$port"
For anyone baffled by this: This works because HTTP/0.9 (just called "HTTP" at the time) worked in an extremely simple way, and browsers mostly retained compatibility for this.
HTTP/0.9 web browser sends:
GET /
Netcat sends:
<!doctype html>
...
Nowadays a browser will send `GET / HTTP/1.1` and then a bunch of headers, which a true HTTP/0.9 server may be able to filter out and ignore, but of course this script will just send the document and the browser will still assume it's a legacy server.
It's absolutely (almost) correct! HTTP/0.9 does not require you to send back a status code or any headers. Some modern web servers even recognise a lone "GET /" to mean HTTP/0.9 and will respond accordingly.
This is exactly my point - it successfully accomplishes a very specific task, in a way that is fragile and context dependent, and completely fails to handle any errors or edge cases, or reckon with any complexity at all.
python -m http.server
But variations exist for a lot of languages. Php has one built-in too