Monday, November 08, 2010 at 12:06 AM.
system.verbs.builtins.webserver.server
on server (adrparamtable, httpRequest=nil) {
<<Thursday, November 11, 1999 at 3:09:25 AM by AR
<<Implemented as a kernel script in Frontier 6.1.
<<Old code
<<on server (adrparamtable, httpRequest=nil)
<<The entrypoint to Frontier's built in web server.
<<paramtable has info about the http request
<<client
<<inetdConfigTableAdr
<<port
<<ready
<<refcon
<<request
<<stream
<<timeout
<<12/19/98; 10:51:51 AM by DW
<<wait until Frontier is finished starting up
<<we have to be concerned about this when Frontier is running behind a web server such as IIS or WebSTAR.
<<10/2/98; 4:36:25 AM by DW
<<carefully reviewed the code, minor streamlining, more work to do later
<<create a new sub-table of paramtable, stats
<<any code in the execution chain can add info to this table
<<to start, we're going to record the value of clock.ticks () at various points in the process
<<9/17/98; 7:34:33 AM by DW
<<added optional httpRequest parameter, allows it to be called directly from tcp.httpClient
<<6/4/98 by RAB
<<Added call to webserve.util.parseCookies
<<while system.temp.Frontier.startingUp //6.0, wait here until Frontier has finished starting up
<<if (defined (user.webserver.prefs.flWaitDuringStartup)) and (not user.webserver.prefs.flWaitDuringStartup) //PBS 3/19/99
<<break
<<thread.sleepFor (1)
<<
<<new (tabletype, @adrparamtable^.stats)
<<adrparamtable^.stats.requestProcessingStarted = clock.ticks ()
<<
<<if httpRequest != nil
<<adrparamtable^.request = httpRequest
<<else
<<adrparamtable^.request = string (webserver.util.readUntil (adrparamtable^.stream, "\r\n\r\n", adrparamtable^.timeout))
<<adrparamtable^.request = string (webserver.util.readUntil (adrparamtable^.stream, "\r\n\r\n", adrparamtable^.timeout))
<<
<<new (tableType, @adrparamtable^.requestHeaders)
<<adrparamtable^.firstLine = webserver.util.parseHeaders (adrparamtable^.request, @adrparamtable^.requestHeaders)
<<
<<if defined (adrparamtable^.requestHeaders.Expect)
<<return (webserver.util.buildResponse (417)) // we can't live up to the client's expectations
<<
<<bundle //now that the headers are parsed, make sure we have the whole body
<<adrparamtable^.requestBody = ""
<<if defined (adrparamtable^.requestHeaders.["Content-Length"])
<<local (len = number (adrparamtable^.requestHeaders.["Content-Length"]))
<<local (ix = string.patternmatch ("\r\n\r\n", adrparamtable^.request))
<<adrparamtable^.requestBody = string.delete (adrparamtable^.request, 1, ix + 3)
<<
<<if sizeOf (adrparamtable^.requestBody) < len
<<local (bytesToRead = len - sizeOf (adrparamtable^.requestBody))
<<local (bytes = webserver.util.readBytes (adrparamtable^.stream, bytesToRead, adrparamtable^.timeout))
<<adrparamtable^.requestBody = adrparamtable^.requestBody + bytes
<<if sizeOf (adrparamtable^.requestBody) < len
<<we couldn't read the whole body for some reason
<<return (webserver.util.buildResponse (400, nil, webserver.util.buildErrorPage ("400 Bad Request", "The request body couldn't be read.")))
<<if sizeOf (adrparamtable^.requestBody) > len // strip off any traling junk
<<adrparamtable^.requestBody = string.delete (adrparamtable^.requestBody, len +1, infinity)
<<
<<local (path, httpVersion)
<<bundle //check for illegal requests
<<path = string.nthField (adrparamtable^.firstLine, " ", 2)
<<if !(path beginsWith "/") && !(path beginsWith "http:") && (path != "*")
<<return (webserver.util.buildResponse (400, nil, webserver.util.buildErrorPage ("400 Bad Request", "All URIs must begin with / or http:")))
<<if path beginsWith "http://"
<<it's a future-style full URL
<<local (pathParts = string.urlSplit (path))
<<path = "/" + pathParts[3]
<<httpVersion = string.nthField (adrparamtable^.firstLine, " ", 3)
<<httpVersion = string.nthField (httpVersion, "/", 2)
<<if httpVersion == "1.1"
<<if not defined (adrparamtable^.requestHeaders.Host)
<<Every HTTP/1.1 request must include a Host header
<<return (webserver.util.buildResponse (400, nil, webserver.util.buildErrorPage ("400 Bad Request", "Every HTTP/1.1 request must include a Host header")))
<<else //PBS 2/28/99: don't call date.versionLessThan on every request: most requests are HTTP 1.1
<<if not date.versionLessThan (httpVersion, "2.0")
<<if the version is 2.0 or greater, we don't know how to handle it
<<return (webserver.util.buildResponse (505, nil, webserver.util.buildErrorPage ("505 Version Not Supported", "This server does not support HTTP/" + httpVersion)))
<<
<<bundle //set up searchArgs and pathArgs
<<adrparamtable^.searchArgs = ""
<<if path contains "?"
<<adrparamtable^.searchArgs = string.nthField (path, "?", 2)
<<path = string.nthField (path, "?", 1)
<<adrparamtable^.pathArgs = ""
<<if not (path contains "$")
<<path = string.replace (path, "%24", "$") //PBS 5/10/99: fix for proxy servers that url encode the $
<<if path contains "$"
<<adrparamtable^.pathArgs = string.nthField (path, "$", 2)
<<path = string.nthField (path, "$", 1)
<<
<<webserver.util.parseCookies (adrparamtable)
<<
<<adrparamtable^.URI = path
<<adrparamtable^.path = path
<<adrparamtable^.method = string.nthField (adrparamtable^.firstLine, " ", 1)
<<try {adrparamtable^.host = adrparamtable^.requestHeaders.host} //PBS 7/31/98
<<
<<local (s = webserver.dispatch (adrparamtable))
<<bundle //6.0, maintain stats, if the feature is turned on
<<if user.webserver.prefs.flStats
<<local (threads = Frontier.countthreads ())
<<if threads > user.webserver.stats.maxConnections
<<user.webserver.stats.maxConnections = threads
<<local (memavail = sys.memavail ())
<<if memavail > user.webserver.stats.maxmemavail
<<user.webserver.stats.maxmemavail = memavail
<<if memavail < user.webserver.stats.minmemavail
<<user.webserver.stats.minmemavail = memavail
<<user.webserver.stats.hits++
<<return (s)
kernel (webserver.server)}
This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.