#!/bin/bash proc http::parse_request { http::read req_line setglobal req_line = '('$req_line) export REQUEST_METHOD=$(req_line[0]) export REQUEST_URI=$(req_line[1]) export REQUEST_PATH=$(REQUEST_URI%%\?*) export QUERY_STRING=$(REQUEST_URI#*\?) export HTTP_VERSION=$(req_line[2]) export SERVER_SOFTWARE="balls/0.0TODO " declare -A HEADERS = '' var key = '' var val = '' while http::read HEADER_LINE { set key = $(HEADER_LINE%%*( ):*) trim key set val = $(HEADER_LINE#*:*( )) trim val HEADERS["$key"]="$val" } } proc http::read { var __var = $1; shift read __in var RETVAL = $Status # f-ing carriage returns setglobal __in = $[echo $__in | tr -d '\r] export "$__var"="$__in" # REQ="$(echo "$REQ"; echo "${!__var}")" test $RETVAL = 0 && test -n $(!__var)TODO } declare -a HTTP_STATUSES = '' HTTP_STATUSES[200]='OK' HTTP_STATUSES[404]='Not Found' HTTP_STATUSES[500]='Internal Server Error' # TODO: lock this so it only happen once proc http::status { var code = $1;shift var message = $1;shift test -z $message && set message = $(HTTP_STATUSES[$code]) http::header_echo "$HTTP_VERSION $code $message" } proc http::header { var header_name = $1;shift var header_val = $1;shift http::header_echo "$header_name: $header_val" } proc http::header_echo { echo @Argv > !3 } proc http::content_type { http::header 'Content-Type' @Argv }