diff options
author | Dominik Picheta <dominikpicheta@gmail.com> | 2020-02-22 11:46:24 +0000 |
---|---|---|
committer | Dominik Picheta <dominikpicheta@googlemail.com> | 2020-03-06 11:52:30 +0100 |
commit | ec8a17cc861c8282ae33ae36030d1702e41b275a (patch) | |
tree | c382e2644c983dd4cb641b8f20d2da743a89b1a5 /lib | |
parent | b80d293a3f8c301a2d9188fb409162028a00edca (diff) | |
download | Nim-ec8a17cc861c8282ae33ae36030d1702e41b275a.tar.gz |
Revert broken asynchttpserver FutureStream additions.
As discussed in #13394, these changes cannot work. Reverted via ``` git revert --no-commit 5bf571f061d53d35aab727f420afd9f415987723 git revert --no-commit abd660c407d00d0c4f2129ff11bfc69badda8ece git revert --no-commit 955465e5f42b1353f69f3bd884908a7ef91ce13b git commit ```
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/asynchttpserver.nim | 176 |
1 files changed, 31 insertions, 145 deletions
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 9aed0255b..186f0da41 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -29,129 +29,43 @@ ## await req.respond(Http200, "Hello World") ## ## waitFor server.serve(Port(8080), cb) -## -## Basic Post request handle -## ========================= -## -## This example will create an HTTP server on port 8080. The server will -## respond with a page with the actual and expected body length after -## submitting a file. -## -## .. code-block::nim -## import asynchttpserver, asyncdispatch -## import strutils, strformat -## -## const stream = true # for test purposes switch from true to false -## -## proc htmlpage(contentLength, bodyLength: int): string = -## return &""" -## <!Doctype html> -## <html lang="en"> -## <head><meta charset="utf-8"/></head> -## <body> -## <form action="/" method="post" enctype="multipart/form-data"> -## File: <input type="file" name="testfile" accept="text/*"><br /> -## <input style="margin:10px 0;" type="submit"> -## </form><br /> -## Expected Body Length: {contentLength} bytes<br /> -## Actual Body Length: {bodyLength} bytes -## </body> -## </html> -## """ -## -## proc cb(req: Request) {.async.} = -## var -## contentLength = 0 -## bodyLength = 0 -## if req.reqMethod == HttpPost: -## contentLength = req.headers["Content-length"].parseInt -## if stream: -## # Read 8*1024 bytes at a time -## # optional chunkSize parameter. The default is 8*1024 -## for length, data in req.bodyStream(8*1024): -## let content = await data -## if length == content.len: -## bodyLength += content.len -## else: -## # Handle exception -## await req.respond(Http400, -## "Bad Request. Data read has a different length than the expected.") -## return -## else: -## bodyLength += req.body.len -## await req.respond(Http200, htmlpage(contentLength, bodyLength)) -## -## let server = newAsyncHttpServer(maxBody = 10485760, stream = stream) # 10 MB -## waitFor server.serve(Port(8080), cb) import tables, asyncnet, asyncdispatch, parseutils, uri, strutils import httpcore export httpcore except parseHeader +const + maxLine = 8*1024 + # TODO: If it turns out that the decisions that asynchttpserver makes # explicitly, about whether to close the client sockets or upgrade them are # wrong, then add a return value which determines what to do for the callback. # Also, maybe move `client` out of `Request` object and into the args for # the proc. - -const - maxLine = 8*1024 - -when (NimMajor, NimMinor) >= (1, 1): - type - Request* = object - client*: AsyncSocket # TODO: Separate this into a Response object? - reqMethod*: HttpMethod - headers*: HttpHeaders - protocol*: tuple[orig: string, major, minor: int] - url*: Uri - hostname*: string ## The hostname of the client that made the request. - body*: string - contentLength*: int - - type - AsyncHttpServer* = ref object - socket: AsyncSocket - reuseAddr: bool - reusePort: bool - maxBody: int ## The maximum content-length that will be read for the body. - stream: bool ## By default (stream = false), the body of the request is read immediately -else: - type - Request* = object - client*: AsyncSocket # TODO: Separate this into a Response object? - reqMethod*: HttpMethod - headers*: HttpHeaders - protocol*: tuple[orig: string, major, minor: int] - url*: Uri - hostname*: string ## The hostname of the client that made the request. - body*: string - - type - AsyncHttpServer* = ref object - socket: AsyncSocket - reuseAddr: bool - reusePort: bool - maxBody: int ## The maximum content-length that will be read for the body. - -when (NimMajor, NimMinor) >= (1, 1): - proc newAsyncHttpServer*(reuseAddr = true, reusePort = false, - maxBody = 8388608, stream = false): AsyncHttpServer = - ## Creates a new ``AsyncHttpServer`` instance. - new result - result.reuseAddr = reuseAddr - result.reusePort = reusePort - result.maxBody = maxBody - result.stream = stream -else: - proc newAsyncHttpServer*(reuseAddr = true, reusePort = false, +type + Request* = object + client*: AsyncSocket # TODO: Separate this into a Response object? + reqMethod*: HttpMethod + headers*: HttpHeaders + protocol*: tuple[orig: string, major, minor: int] + url*: Uri + hostname*: string ## The hostname of the client that made the request. + body*: string + + AsyncHttpServer* = ref object + socket: AsyncSocket + reuseAddr: bool + reusePort: bool + maxBody: int ## The maximum content-length that will be read for the body. + +proc newAsyncHttpServer*(reuseAddr = true, reusePort = false, maxBody = 8388608): AsyncHttpServer = - ## Creates a new ``AsyncHttpServer`` instance. - new result - result.reuseAddr = reuseAddr - result.reusePort = reusePort - result.maxBody = maxBody + ## Creates a new ``AsyncHttpServer`` instance. + new result + result.reuseAddr = reuseAddr + result.reusePort = reusePort + result.maxBody = maxBody proc addHeaders(msg: var string, headers: HttpHeaders) = for k, v in headers: @@ -214,30 +128,13 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] = proc sendStatus(client: AsyncSocket, status: string): Future[void] = client.send("HTTP/1.1 " & status & "\c\L\c\L") -when (NimMajor, NimMinor) >= (1, 1): - iterator bodyStream*( - request: Request, - chunkSize: int = 8*1024): (int, Future[string]) = - ## The chunkSize parameter is optional and default value is 8*1024 bytes. - ## - ## This iterator return a tuple with the length of the data that was read - ## and a future. - var remainder = request.contentLength - while remainder > 0: - let readSize = min(remainder, chunkSize) - let data = request.client.recv(readSize) - if data.failed: - raise newException(ValueError, "Error reading POST data from client.") - yield (readSize, data) - remainder -= readSize - proc processRequest( server: AsyncHttpServer, req: FutureVar[Request], client: AsyncSocket, address: string, lineFut: FutureVar[string], - callback: proc (request: Request): Future[void] {.closure, gcsafe.} + 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. @@ -248,12 +145,10 @@ proc processRequest( # Header: val # \n request.headers.clear() + request.body = "" request.hostname.shallowCopy(address) assert client != nil request.client = client - request.body = "" - when (NimMajor, NimMinor) >= (1, 1): - request.contentLength = 0 # We should skip at least one empty line before the request # https://tools.ietf.org/html/rfc7230#section-3.5 @@ -348,19 +243,10 @@ proc processRequest( if contentLength > server.maxBody: await request.respondError(Http413) return false - - when (NimMajor, NimMinor) >= (1, 1): - request.contentLength = contentLength - if not server.stream: - request.body = await client.recv(contentLength) - if request.body.len != contentLength: - await request.respond(Http400, "Bad Request. Content-Length does not match actual.") - return true - else: - request.body = await client.recv(contentLength) - if request.body.len != contentLength: - await request.respond(Http400, "Bad Request. Content-Length does not match actual.") - return true + request.body = await client.recv(contentLength) + if request.body.len != contentLength: + await request.respond(Http400, "Bad Request. Content-Length does not match actual.") + return true elif request.reqMethod == HttpPost: await request.respond(Http411, "Content-Length required.") return true |