proc get { route "GET" $ifsjoin(ARGV) } proc post { route "POST" $ifsjoin(ARGV) } proc delete { route "DELETE" $ifsjoin(ARGV) } proc status { setglobal martin_response_status = $1 } proc header { setglobal martin_response_headers = ""$martin_response_headers$1: $2$LF"" } proc not_found { status "404" header "Content-type" "text/plain" if test $Argc -gt 0 { echo @ARGV } else { echo "Not Found: $PATH_INFO" } } setglobal LF = '$'\n'' # route: method, path, action setglobal martin_routes = ''"" proc route { setglobal martin_routes = ""$martin_routes$1,$2,$3$LF"" } proc martin_find_route { echo $martin_routes | while env IFS="," read -r method path action { if test $1 = $method && test $2 = $path { echo $action return } } } setglobal martin_response_headers = ''"" setglobal martin_response_status = ''"" setglobal martin_response_file = ""$TMPDIR/martin_response$Pid"" proc martin_reset_response { setglobal martin_response_status = '"200 OK'" setglobal martin_response_headers = ''"" } proc martin_dispatch { local action="$[martin_find_route $REQUEST_METHOD $PATH_INFO]" test ! $action && setglobal action = '"not_found'" martin_reset_response # execute the action, storing output in a temporary file $action > "$martin_response_file" # set status header and content-length header header "Status" $martin_response_status header "Content-Length" $[wc -c $martin_response_file | awk '{ print $1 }] # echo headers, blank line, then body echo $martin_response_headers cat $martin_response_file } proc martin { if test $REQUEST_METHOD { # as a CGI script martin_dispatch } else { # standalone using the wwwoosh server source ./wwwoosh.sh wwwoosh martin_dispatch $PORT } }