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.