#!/usr/bin/gawk -f # # # S I M P L E W E B S E R V E R F R A M E W O R K # --------------------------------------------------- # function skipws(string) { sub(/^[ \t]+/, "", string); return (string); } function noctrl(string) { sub(/[ \t\r]+$/, "", string); return (string); } # # P A R T 1 - R E A D I N G T H E C L I E N T R E Q U E S T # --------------------------------------------------------------------- # # Calling readrequest() read the client's request, sets the arrays # REQUEST, HEADER and CGIVAR and returns the request's URI. # function readline( line) { if (getline line > 0) { gsub(/\r/, "", line); return (line); } return ("\001"); } function decodecgi(value, result, k, a, b, c) { HEX = "123456789ABCDEF"; result = ""; while ((k = index(value, "%")) > 0) { a = substr(value, k+1, 1); b = substr(value, k+2, 1); c = sprintf ("%c", index(HEX, a) * 16 + index(HEX, b)); result = result substr(value, 1, k-1) c; value = substr(value, k+3); } result = result value; return (result); } function getcgivars(string, i, k, n, x) { gsub(/\+/, " ", string); n = split(string, x, "&"); for (i=1; i<=n; i++) { if ((k = index(x[i], "=")) > 0) CGIVAR[tolower(substr(x[i], 1, k-1))] = decodecgi(substr(x[i], k+1)); } } function readrequest( k, headername, value) { if (($0 = readline()) == "\001") { printf ("Broken request.\n") >"/dev/stderr"; return (""); } REQUEST["method"] = $1; REQUEST["protocol"] = $3; if ((k = index($2, "?")) == 0) REQUEST["selector"] = $2; else { REQUEST["query"] = substr($2, k+1); REQUEST["selector"] = substr($2, 1, k-1); getcgivars(REQUEST["query"]); } while ((line = readline()) != "\001" && line != "") { if ((k = index(line, ":")) > 0) { headername = tolower(substr(line, 1, k-1)); value = skipws(substr(line, k+1)); HEADER[headername] = value; } } return (REQUEST["selector"]); } # # P A R T 2 - O U T P U T R E L A T E D F U N C T I O N S # ----------------------------------------------------------------- # # The following functions handle "send output to client" # tasks. # function httpheader(code, message, type, data) { printf ("HTTP/1.0 %d %s\r\n", code, message); if (type != "") printf ("Content-Type: %s\r\n", type); printf ("\r\n"); return (0); } function starthtml(title, printbody) { printf ("\n"); printf ("\n"); printf (" %s\n", title); printf ("\n"); if (printbody != 0) printf ("\n"); return (0); } function endhtml() { printf ("\n"); printf ("\n"); return (0); } function senderror(code, message) { httpheader(code, message, "text/html"); starthtml(message, 1); printf ("%s %s: %s
\n", code, message, REQUEST["selector"]); endhtml(); return (0); } function printtest() { printf ("method: %s
\n", REQUEST["method"]); printf ("selector: %s
\n", REQUEST["selector"]); if (REQUEST["query"] != "") printf ("query-string: %s
\n", REQUEST["query"]); printf ("protocol: %s
\n", REQUEST["protocol"]); printf ("

\n"); if (REQUEST["selector"] != "") { for (var in CGIVAR) printf ("%s: %s
\n", var, CGIVAR[var]); printf ("

\n"); } for (name in HEADER) { printf ("%s: %s
\n", name, HEADER[name]); wantp = 1 } return (0); } # # P A R T 3 - S E R V I N G R E Q U E S T S # ------------------------------------------------- # BEGIN { if ((URI = readrequest()) == "") exit (1); if (URI == "/no.such.page") { senderror(404, "File not found"); } else { httpheader(200, "OK", "text/html"); starthtml("Test Output", 1); printtest(); endhtml(); } exit (0); }