diff options
author | Dominik Picheta <dominikpicheta@googlemail.com> | 2018-12-27 21:26:48 +0000 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-12-27 22:26:48 +0100 |
commit | e3cee541bd74cc9acc6b3682afd94eb17736f6ae (patch) | |
tree | ce4aba215f04ae831e0273b9afe94fbcd5b7f949 /lib/pure | |
parent | 513a287c61e6e461b013e75a7f5dbfa0136b606c (diff) | |
download | Nim-e3cee541bd74cc9acc6b3682afd94eb17736f6ae.tar.gz |
Fixes long-standing asynchttpserver regression. (#10102)
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/asynchttpserver.nim | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index d27c2fb9c..e3fc75597 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -143,11 +143,14 @@ proc parseUppercaseMethod(name: string): HttpMethod = of "TRACE": HttpTrace else: raise newException(ValueError, "Invalid HTTP method " & name) -proc processRequest(server: AsyncHttpServer, req: FutureVar[Request], - client: AsyncSocket, - address: string, lineFut: FutureVar[string], - callback: proc (request: Request): - Future[void] {.closure, gcsafe.}) {.async.} = +proc processRequest( + server: AsyncHttpServer, + req: FutureVar[Request], + client: AsyncSocket, + address: string, + lineFut: FutureVar[string], + callback: proc (request: Request): Future[void] {.closure, gcsafe.}, +): Future[bool] {.async.} = # Alias `request` to `req.mget()` so we don't have to write `mget` everywhere. template request(): Request = @@ -171,12 +174,12 @@ proc processRequest(server: AsyncHttpServer, req: FutureVar[Request], if lineFut.mget == "": client.close() - return + return false if lineFut.mget.len > maxLine: await request.respondError(Http413) client.close() - return + return false if lineFut.mget != "\c\L": break @@ -189,22 +192,22 @@ proc processRequest(server: AsyncHttpServer, req: FutureVar[Request], request.reqMethod = parseUppercaseMethod(linePart) except ValueError: asyncCheck request.respondError(Http400) - return + return true # Retry processing of request of 1: try: parseUri(linePart, request.url) except ValueError: asyncCheck request.respondError(Http400) - return + return true of 2: try: request.protocol = parseProtocol(linePart) except ValueError: asyncCheck request.respondError(Http400) - return + return true else: await request.respondError(Http400) - return + return true inc i # Headers @@ -215,10 +218,10 @@ proc processRequest(server: AsyncHttpServer, req: FutureVar[Request], await client.recvLineInto(lineFut, maxLength=maxLine) if lineFut.mget == "": - client.close(); return + client.close(); return false if lineFut.mget.len > maxLine: await request.respondError(Http413) - client.close(); return + client.close(); return false if lineFut.mget == "\c\L": break let (key, value) = parseHeader(lineFut.mget) request.headers[key] = value @@ -226,7 +229,7 @@ proc processRequest(server: AsyncHttpServer, req: FutureVar[Request], if request.headers.len > headerLimit: await client.sendStatus("400 Bad Request") request.client.close() - return + return false if request.reqMethod == HttpPost: # Check for Expect header @@ -242,24 +245,24 @@ proc processRequest(server: AsyncHttpServer, req: FutureVar[Request], var contentLength = 0 if parseSaturatedNatural(request.headers["Content-Length"], contentLength) == 0: await request.respond(Http400, "Bad Request. Invalid Content-Length.") - return + return true else: if contentLength > server.maxBody: await request.respondError(Http413) - return + return false request.body = await client.recv(contentLength) if request.body.len != contentLength: await request.respond(Http400, "Bad Request. Content-Length does not match actual.") - return + return true elif request.reqMethod == HttpPost: await request.respond(Http411, "Content-Length required.") - return + return true # Call the user's callback. await callback(request) if "upgrade" in request.headers.getOrDefault("connection"): - return + return false # Persistent connections if (request.protocol == HttpVer11 and @@ -273,7 +276,7 @@ proc processRequest(server: AsyncHttpServer, req: FutureVar[Request], discard else: request.client.close() - return + return false proc processClient(server: AsyncHttpServer, client: AsyncSocket, address: string, callback: proc (request: Request): @@ -285,7 +288,10 @@ proc processClient(server: AsyncHttpServer, client: AsyncSocket, address: string lineFut.mget() = newStringOfCap(80) while not client.isClosed: - await processRequest(server, request, client, address, lineFut, callback) + let retry = await processRequest( + server, request, client, address, lineFut, callback + ) + if not retry: break proc serve*(server: AsyncHttpServer, port: Port, callback: proc (request: Request): Future[void] {.closure,gcsafe.}, |