@@ -35,24 +35,41 @@ import httpcore
3535
3636export httpcore except parseHeader
3737
38- const
39- maxLine = 8 * 1024
40-
4138# TODO : If it turns out that the decisions that asynchttpserver makes
4239# explicitly, about whether to close the client sockets or upgrade them are
4340# wrong, then add a return value which determines what to do for the callback.
4441# Also, maybe move `client` out of `Request` object and into the args for
4542# the proc.
46- type
47- Request * = object
48- client* : AsyncSocket # TODO : Separate this into a Response object?
49- reqMethod* : HttpMethod
50- headers* : HttpHeaders
51- protocol* : tuple [orig: string , major, minor: int ]
52- url* : Uri
53- hostname* : string # # The hostname of the client that made the request.
54- body* : string
5543
44+ const
45+ maxLine = 8 * 1024
46+
47+ when (NimMajor , NimMinor ) >= (1 , 1 ):
48+ const
49+ chunkSize = 8 * 1048 # # This seems perfectly reasonable for default chunkSize.
50+
51+ type
52+ Request * = object
53+ client* : AsyncSocket # TODO : Separate this into a Response object?
54+ reqMethod* : HttpMethod
55+ headers* : HttpHeaders
56+ protocol* : tuple [orig: string , major, minor: int ]
57+ url* : Uri
58+ hostname* : string # # The hostname of the client that made the request.
59+ body* : string
60+ bodyStream* : FutureStream [string ]
61+ else :
62+ type
63+ Request * = object
64+ client* : AsyncSocket # TODO : Separate this into a Response object?
65+ reqMethod* : HttpMethod
66+ headers* : HttpHeaders
67+ protocol* : tuple [orig: string , major, minor: int ]
68+ url* : Uri
69+ hostname* : string # # The hostname of the client that made the request.
70+ body* : string
71+
72+ type
5673 AsyncHttpServer * = ref object
5774 socket: AsyncSocket
5875 reuseAddr: bool
@@ -149,6 +166,8 @@ proc processRequest(
149166 request.hostname.shallowCopy (address)
150167 assert client != nil
151168 request.client = client
169+ when (NimMajor , NimMinor ) >= (1 , 1 ):
170+ request.bodyStream = newFutureStream [string ]()
152171
153172 # We should skip at least one empty line before the request
154173 # https://tools.ietf.org/html/rfc7230#section-3.5
@@ -243,10 +262,23 @@ proc processRequest(
243262 if contentLength > server.maxBody:
244263 await request.respondError (Http413 )
245264 return false
246- request.body = await client.recv (contentLength)
247- if request.body.len != contentLength:
248- await request.respond (Http400 , " Bad Request. Content-Length does not match actual." )
249- return true
265+
266+ when (NimMajor , NimMinor ) >= (1 , 1 ):
267+ var remainder = contentLength
268+ while remainder > 0 :
269+ let readSize = min (remainder, chunkSize)
270+ let data = await client.recv (read_size)
271+ if data.len != read_size:
272+ await request.respond (Http400 , " Bad Request. Content-Length does not match actual." )
273+ return true
274+ await request.bodyStream.write (data)
275+ remainder -= data.len
276+ request.bodyStream.complete ()
277+ else :
278+ request.body = await client.recv (contentLength)
279+ if request.body.len != contentLength:
280+ await request.respond (Http400 , " Bad Request. Content-Length does not match actual." )
281+ return true
250282 elif request.reqMethod == HttpPost :
251283 await request.respond (Http411 , " Content-Length required." )
252284 return true
0 commit comments