Skip to content

Commit 707d057

Browse files
committed
Revert broken asynchttpserver FutureStream additions.
As discussed in #13394, these changes cannot work. Reverted via ``` git revert --no-commit 5bf571f git revert --no-commit abd660c git revert --no-commit 955465e git commit ```
1 parent c11b91d commit 707d057

File tree

2 files changed

+31
-147
lines changed

2 files changed

+31
-147
lines changed

changelog.md

-2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@
7272

7373
## Library changes
7474

75-
- `asynchttpserver` added an iterator that allows the request body to be read in
76-
chunks of data when new server "stream" option is set to true.
7775
- `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations`
7876
and only returns once all pending async operations are guaranteed to have completed.
7977
- `asyncdispatch.drain` now consistently uses the passed timeout value for all

lib/pure/asynchttpserver.nim

+31-145
Original file line numberDiff line numberDiff line change
@@ -29,129 +29,43 @@
2929
## await req.respond(Http200, "Hello World")
3030
##
3131
## waitFor server.serve(Port(8080), cb)
32-
##
33-
## Basic Post request handle
34-
## =========================
35-
##
36-
## This example will create an HTTP server on port 8080. The server will
37-
## respond with a page with the actual and expected body length after
38-
## submitting a file.
39-
##
40-
## .. code-block::nim
41-
## import asynchttpserver, asyncdispatch
42-
## import strutils, strformat
43-
##
44-
## const stream = true # for test purposes switch from true to false
45-
##
46-
## proc htmlpage(contentLength, bodyLength: int): string =
47-
## return &"""
48-
## <!Doctype html>
49-
## <html lang="en">
50-
## <head><meta charset="utf-8"/></head>
51-
## <body>
52-
## <form action="/" method="post" enctype="multipart/form-data">
53-
## File: <input type="file" name="testfile" accept="text/*"><br />
54-
## <input style="margin:10px 0;" type="submit">
55-
## </form><br />
56-
## Expected Body Length: {contentLength} bytes<br />
57-
## Actual Body Length: {bodyLength} bytes
58-
## </body>
59-
## </html>
60-
## """
61-
##
62-
## proc cb(req: Request) {.async.} =
63-
## var
64-
## contentLength = 0
65-
## bodyLength = 0
66-
## if req.reqMethod == HttpPost:
67-
## contentLength = req.headers["Content-length"].parseInt
68-
## if stream:
69-
## # Read 8*1024 bytes at a time
70-
## # optional chunkSize parameter. The default is 8*1024
71-
## for length, data in req.bodyStream(8*1024):
72-
## let content = await data
73-
## if length == content.len:
74-
## bodyLength += content.len
75-
## else:
76-
## # Handle exception
77-
## await req.respond(Http400,
78-
## "Bad Request. Data read has a different length than the expected.")
79-
## return
80-
## else:
81-
## bodyLength += req.body.len
82-
## await req.respond(Http200, htmlpage(contentLength, bodyLength))
83-
##
84-
## let server = newAsyncHttpServer(maxBody = 10485760, stream = stream) # 10 MB
85-
## waitFor server.serve(Port(8080), cb)
8632

8733
import tables, asyncnet, asyncdispatch, parseutils, uri, strutils
8834
import httpcore
8935

9036
export httpcore except parseHeader
9137

38+
const
39+
maxLine = 8*1024
40+
9241
# TODO: If it turns out that the decisions that asynchttpserver makes
9342
# explicitly, about whether to close the client sockets or upgrade them are
9443
# wrong, then add a return value which determines what to do for the callback.
9544
# Also, maybe move `client` out of `Request` object and into the args for
9645
# the proc.
97-
98-
const
99-
maxLine = 8*1024
100-
101-
when (NimMajor, NimMinor) >= (1, 1):
102-
type
103-
Request* = object
104-
client*: AsyncSocket # TODO: Separate this into a Response object?
105-
reqMethod*: HttpMethod
106-
headers*: HttpHeaders
107-
protocol*: tuple[orig: string, major, minor: int]
108-
url*: Uri
109-
hostname*: string ## The hostname of the client that made the request.
110-
body*: string
111-
contentLength*: int
112-
113-
type
114-
AsyncHttpServer* = ref object
115-
socket: AsyncSocket
116-
reuseAddr: bool
117-
reusePort: bool
118-
maxBody: int ## The maximum content-length that will be read for the body.
119-
stream: bool ## By default (stream = false), the body of the request is read immediately
120-
else:
121-
type
122-
Request* = object
123-
client*: AsyncSocket # TODO: Separate this into a Response object?
124-
reqMethod*: HttpMethod
125-
headers*: HttpHeaders
126-
protocol*: tuple[orig: string, major, minor: int]
127-
url*: Uri
128-
hostname*: string ## The hostname of the client that made the request.
129-
body*: string
130-
131-
type
132-
AsyncHttpServer* = ref object
133-
socket: AsyncSocket
134-
reuseAddr: bool
135-
reusePort: bool
136-
maxBody: int ## The maximum content-length that will be read for the body.
137-
138-
when (NimMajor, NimMinor) >= (1, 1):
139-
proc newAsyncHttpServer*(reuseAddr = true, reusePort = false,
140-
maxBody = 8388608, stream = false): AsyncHttpServer =
141-
## Creates a new ``AsyncHttpServer`` instance.
142-
new result
143-
result.reuseAddr = reuseAddr
144-
result.reusePort = reusePort
145-
result.maxBody = maxBody
146-
result.stream = stream
147-
else:
148-
proc newAsyncHttpServer*(reuseAddr = true, reusePort = false,
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
55+
56+
AsyncHttpServer* = ref object
57+
socket: AsyncSocket
58+
reuseAddr: bool
59+
reusePort: bool
60+
maxBody: int ## The maximum content-length that will be read for the body.
61+
62+
proc newAsyncHttpServer*(reuseAddr = true, reusePort = false,
14963
maxBody = 8388608): AsyncHttpServer =
150-
## Creates a new ``AsyncHttpServer`` instance.
151-
new result
152-
result.reuseAddr = reuseAddr
153-
result.reusePort = reusePort
154-
result.maxBody = maxBody
64+
## Creates a new ``AsyncHttpServer`` instance.
65+
new result
66+
result.reuseAddr = reuseAddr
67+
result.reusePort = reusePort
68+
result.maxBody = maxBody
15569

15670
proc addHeaders(msg: var string, headers: HttpHeaders) =
15771
for k, v in headers:
@@ -214,30 +128,13 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] =
214128
proc sendStatus(client: AsyncSocket, status: string): Future[void] =
215129
client.send("HTTP/1.1 " & status & "\c\L\c\L")
216130

217-
when (NimMajor, NimMinor) >= (1, 1):
218-
iterator bodyStream*(
219-
request: Request,
220-
chunkSize: int = 8*1024): (int, Future[string]) =
221-
## The chunkSize parameter is optional and default value is 8*1024 bytes.
222-
##
223-
## This iterator return a tuple with the length of the data that was read
224-
## and a future.
225-
var remainder = request.contentLength
226-
while remainder > 0:
227-
let readSize = min(remainder, chunkSize)
228-
let data = request.client.recv(readSize)
229-
if data.failed:
230-
raise newException(ValueError, "Error reading POST data from client.")
231-
yield (readSize, data)
232-
remainder -= readSize
233-
234131
proc processRequest(
235132
server: AsyncHttpServer,
236133
req: FutureVar[Request],
237134
client: AsyncSocket,
238135
address: string,
239136
lineFut: FutureVar[string],
240-
callback: proc (request: Request): Future[void] {.closure, gcsafe.}
137+
callback: proc (request: Request): Future[void] {.closure, gcsafe.},
241138
): Future[bool] {.async.} =
242139

243140
# Alias `request` to `req.mget()` so we don't have to write `mget` everywhere.
@@ -248,12 +145,10 @@ proc processRequest(
248145
# Header: val
249146
# \n
250147
request.headers.clear()
148+
request.body = ""
251149
request.hostname.shallowCopy(address)
252150
assert client != nil
253151
request.client = client
254-
request.body = ""
255-
when (NimMajor, NimMinor) >= (1, 1):
256-
request.contentLength = 0
257152

258153
# We should skip at least one empty line before the request
259154
# https://tools.ietf.org/html/rfc7230#section-3.5
@@ -348,19 +243,10 @@ proc processRequest(
348243
if contentLength > server.maxBody:
349244
await request.respondError(Http413)
350245
return false
351-
352-
when (NimMajor, NimMinor) >= (1, 1):
353-
request.contentLength = contentLength
354-
if not server.stream:
355-
request.body = await client.recv(contentLength)
356-
if request.body.len != contentLength:
357-
await request.respond(Http400, "Bad Request. Content-Length does not match actual.")
358-
return true
359-
else:
360-
request.body = await client.recv(contentLength)
361-
if request.body.len != contentLength:
362-
await request.respond(Http400, "Bad Request. Content-Length does not match actual.")
363-
return true
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
364250
elif request.reqMethod == HttpPost:
365251
await request.respond(Http411, "Content-Length required.")
366252
return true

0 commit comments

Comments
 (0)