--- /dev/null
+#!/usr/bin/env zsh
+# zws -- Z Shell-based Web server
+# Copyright (C) 2024 Sergey Matveev <stargrave@stargrave.org>
+# Serves static files, directory listings and MIME types
+# Usage: tcpserver -DHR -l 0 ::0 80 ./zws
+
+setopt ERR_EXIT PIPE_FAIL
+
+while read l ; do
+ local cols=(${=l})
+ [[ ${#cols} -ge 2 ]] || break
+ [[ $cols && ${cols[1]} = GET ]] || continue
+ REQPATH=${cols[2]}
+done
+
+doreply() {
+ local ct=$1
+ [[ -n $ct ]]
+ local code=${2:-200 OK}
+ print "HTTP/1.1 $code\r"
+ print "Server: zws/0.1.0\r"
+ print "Connection: close\r"
+ print "Cache-Control: no-cache\r"
+ print "Content-Type: $ct\r"
+ print "\r"
+}
+
+notfound() {
+ doreply text/plain "404 NOT FOUND"
+ exit 0
+}
+
+REQPATH=(${(s/?/)REQPATH})
+REQQUERY=${REQPATH[2]}
+REQPATH=${REQPATH[1]}
+[[ $REQPATH =~ "/\.\./" ]] && notfound
+
+REQPATH=${REQPATH#/}
+if [[ (-z $REQPATH) || ($REQPATH =~ "/$") ]] ; then
+ [[ (-n $REQPATH) && (! -d $REQPATH) ]] && notfound || :
+ doreply text/html
+ cat <<EOF
+<!DOCTYPE html>
+<html><head>
+ <title>$REQPATH</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head><body>
+<table border=1>
+<tr><th> </th><th>name</th><th>mtime</th><th>size</th></tr>
+EOF
+ [[ -z $REQPATH ]] || cd $REQPATH
+ ctr=0
+ zmodload -F zsh/stat b:zstat
+ zmodload -F zsh/datetime b:strftime
+ for i (*(onN)) {
+ zstat -A mtimeSec +mtime $i
+ strftime -s mtime "%Y-%m-%d %H:%M:%S" $mtimeSec
+ zstat -A size +size $i
+ [[ ! -d $i ]] || i="$i/"
+ print "<tr><td>$ctr</td><td><a href=\"$i\">$i</a></td>"
+ print "<td>$mtime</td><td>$size</td></tr>"
+ ctr=$(( $ctr + 1 ))
+ }
+ print "</table></body></html>"
+ exit 0
+fi
+
+[[ -r $REQPATH ]] || notfound
+
+ct=application/octet-stream
+case $REQPATH:e in
+txt) ct=text/plain ;;
+html) ct=text/html ;;
+esac
+
+doreply $ct
+_cat=cat
+[[ $REQQUERY =~ "tai64nlocal=1" ]] && _cat=tai64nlocal
+$_cat < $REQPATH