diff options
Diffstat (limited to 'lib/pure/httpserver.nim')
-rw-r--r-- | lib/pure/httpserver.nim | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/lib/pure/httpserver.nim b/lib/pure/httpserver.nim index 5efdbe297..71ba04991 100644 --- a/lib/pure/httpserver.nim +++ b/lib/pure/httpserver.nim @@ -106,9 +106,10 @@ proc serveFile*(client: Socket, filename: string) = when false: # TODO: Fix this, or get rid of it. type - TRequestMethod = enum reqGet, reqPost + RequestMethod = enum reqGet, reqPost + {.deprecated: [TRequestMethod: RequestMethod].} - proc executeCgi(client: Socket, path, query: string, meth: TRequestMethod) = + proc executeCgi(client: Socket, path, query: string, meth: RequestMethod) = var env = newStringTable(modeCaseInsensitive) var contentLength = -1 case meth @@ -141,7 +142,7 @@ when false: if meth == reqPost: # get from client and post to CGI program: var buf = alloc(contentLength) - if recv(client, buf, contentLength) != contentLength: + if recv(client, buf, contentLength) != contentLength: dealloc(buf) raiseOSError() var inp = process.inputStream @@ -176,7 +177,7 @@ when false: else: path = "." & data[1] # path starts with "/", by adding "." in front of it we serve files from cwd - + if cmpIgnoreCase(data[0], "GET") == 0: if q >= 0: cgi = true @@ -208,7 +209,7 @@ when false: executeCgi(client, path, query, meth) type - TServer* = object of RootObj ## contains the current server state + Server* = object of RootObj ## contains the current server state socket: Socket port: Port client*: Socket ## the socket to write the file data to @@ -217,12 +218,13 @@ type headers*: StringTableRef ## headers with which the client made the request body*: string ## only set with POST requests ip*: string ## ip address of the requesting client - - PAsyncHTTPServer* = ref TAsyncHTTPServer - TAsyncHTTPServer = object of TServer + + PAsyncHTTPServer* = ref AsyncHTTPServer + AsyncHTTPServer = object of Server asyncSocket: AsyncSocket - -proc open*(s: var TServer, port = Port(80), reuseAddr = false) = +{.deprecated: [TAsyncHTTPServer: AsyncHTTPServer, TServer: Server].} + +proc open*(s: var Server, port = Port(80), reuseAddr = false) = ## creates a new server at port `port`. If ``port == 0`` a free port is ## acquired that can be accessed later by the ``port`` proc. s.socket = socket(AF_INET) @@ -243,11 +245,11 @@ proc open*(s: var TServer, port = Port(80), reuseAddr = false) = s.query = "" s.headers = {:}.newStringTable() -proc port*(s: var TServer): Port = +proc port*(s: var Server): Port = ## get the port number the server has acquired. result = s.port -proc next*(s: var TServer) = +proc next*(s: var Server) = ## proceed to the first/next request. var client: Socket new(client) @@ -260,7 +262,7 @@ proc next*(s: var TServer) = var data = "" s.client.readLine(data) if data == "": - # Socket disconnected + # Socket disconnected s.client.close() next(s) return @@ -281,9 +283,9 @@ proc next*(s: var TServer) = s.client.close() next(s) return - + var i = skipWhitespace(data) - if skipIgnoreCase(data, "GET") > 0: + if skipIgnoreCase(data, "GET") > 0: s.reqMethod = "GET" inc(i, 3) elif skipIgnoreCase(data, "POST") > 0: @@ -294,7 +296,7 @@ proc next*(s: var TServer) = s.client.close() next(s) return - + if s.reqMethod == "POST": # Check for Expect header if s.headers.hasKey("Expect"): @@ -302,7 +304,7 @@ proc next*(s: var TServer) = s.client.sendStatus("100 Continue") else: s.client.sendStatus("417 Expectation Failed") - + # Read the body # - Check for Content-length header if s.headers.hasKey("Content-Length"): @@ -338,13 +340,13 @@ proc next*(s: var TServer) = s.client.close() next(s) return - + var L = skipWhitespace(data, i) inc(i, L) # XXX we ignore "HTTP/1.1" etc. for now here var query = 0 var last = i - while last < data.len and data[last] notin Whitespace: + while last < data.len and data[last] notin Whitespace: if data[last] == '?' and query == 0: query = last inc(last) if query > 0: @@ -354,15 +356,15 @@ proc next*(s: var TServer) = s.query = "" s.path = data.substr(i, last-1) -proc close*(s: TServer) = +proc close*(s: Server) = ## closes the server (and the socket the server uses). close(s.socket) -proc run*(handleRequest: proc (client: Socket, +proc run*(handleRequest: proc (client: Socket, path, query: string): bool {.closure.}, port = Port(80)) = ## encapsulates the server object and main loop - var s: TServer + var s: Server open(s, port, reuseAddr = true) #echo("httpserver running on port ", s.port) while true: @@ -386,7 +388,7 @@ proc nextAsync(s: PAsyncHTTPServer) = var data = "" s.client.readLine(data) if data == "": - # Socket disconnected + # Socket disconnected s.client.close() return var header = "" @@ -406,9 +408,9 @@ proc nextAsync(s: PAsyncHTTPServer) = else: s.client.close() return - + var i = skipWhitespace(data) - if skipIgnoreCase(data, "GET") > 0: + if skipIgnoreCase(data, "GET") > 0: s.reqMethod = "GET" inc(i, 3) elif skipIgnoreCase(data, "POST") > 0: @@ -418,7 +420,7 @@ proc nextAsync(s: PAsyncHTTPServer) = unimplemented(s.client) s.client.close() return - + if s.reqMethod == "POST": # Check for Expect header if s.headers.hasKey("Expect"): @@ -426,7 +428,7 @@ proc nextAsync(s: PAsyncHTTPServer) = s.client.sendStatus("100 Continue") else: s.client.sendStatus("417 Expectation Failed") - + # Read the body # - Check for Content-length header if s.headers.hasKey("Content-Length"): @@ -458,13 +460,13 @@ proc nextAsync(s: PAsyncHTTPServer) = badRequest(s.client) s.client.close() return - + var L = skipWhitespace(data, i) inc(i, L) # XXX we ignore "HTTP/1.1" etc. for now here var query = 0 var last = i - while last < data.len and data[last] notin Whitespace: + while last < data.len and data[last] notin Whitespace: if data[last] == '?' and query == 0: query = last inc(last) if query > 0: @@ -474,7 +476,7 @@ proc nextAsync(s: PAsyncHTTPServer) = s.query = "" s.path = data.substr(i, last-1) -proc asyncHTTPServer*(handleRequest: proc (server: PAsyncHTTPServer, client: Socket, +proc asyncHTTPServer*(handleRequest: proc (server: PAsyncHTTPServer, client: Socket, path, query: string): bool {.closure, gcsafe.}, port = Port(80), address = "", reuseAddr = false): PAsyncHTTPServer = @@ -490,14 +492,14 @@ proc asyncHTTPServer*(handleRequest: proc (server: PAsyncHTTPServer, client: Soc if quit: capturedRet.asyncSocket.close() if reuseAddr: capturedRet.asyncSocket.setSockOpt(OptReuseAddr, true) - + capturedRet.asyncSocket.bindAddr(port, address) capturedRet.asyncSocket.listen() if port == Port(0): capturedRet.port = getSockName(capturedRet.asyncSocket) else: capturedRet.port = port - + capturedRet.client = invalidSocket capturedRet.reqMethod = "" capturedRet.body = "" @@ -514,19 +516,19 @@ proc close*(h: PAsyncHTTPServer) = ## Closes the ``PAsyncHTTPServer``. h.asyncSocket.close() -when isMainModule: +when not defined(testing) and isMainModule: var counter = 0 - var s: TServer + var s: Server open(s, Port(0)) echo("httpserver running on port ", s.port) while true: next(s) - + inc(counter) s.client.send("Hello, Andreas, for the $#th time. $# ? $#" % [ $counter, s.path, s.query] & wwwNL) - + close(s.client) close(s) |