Add support for Transfer-Encoding: chunked (#16636)
* Add support for Transfer-Encoding: chunked * Minor whitespace fixes * Use recv instead of recvLineInto * Undo changes to httpcore, inline changes
This commit is contained in:
parent
dbff2cd938
commit
65df5762a1
1 changed files with 44 additions and 0 deletions
|
|
@ -142,6 +142,17 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] =
|
||||||
proc sendStatus(client: AsyncSocket, status: string): Future[void] =
|
proc sendStatus(client: AsyncSocket, status: string): Future[void] =
|
||||||
client.send("HTTP/1.1 " & status & "\c\L\c\L")
|
client.send("HTTP/1.1 " & status & "\c\L\c\L")
|
||||||
|
|
||||||
|
func hasChunkedEncoding(request: Request): bool =
|
||||||
|
## Searches for a chunked transfer encoding
|
||||||
|
const transferEncoding = "Transfer-Encoding"
|
||||||
|
|
||||||
|
if request.headers.hasKey(transferEncoding):
|
||||||
|
for encoding in seq[string](request.headers[transferEncoding]):
|
||||||
|
if "chunked" == encoding.strip:
|
||||||
|
# Returns true if it is both an HttpPost and has chunked encoding
|
||||||
|
return request.reqMethod == HttpPost
|
||||||
|
return false
|
||||||
|
|
||||||
proc processRequest(
|
proc processRequest(
|
||||||
server: AsyncHttpServer,
|
server: AsyncHttpServer,
|
||||||
req: FutureVar[Request],
|
req: FutureVar[Request],
|
||||||
|
|
@ -261,6 +272,39 @@ proc processRequest(
|
||||||
if request.body.len != contentLength:
|
if request.body.len != contentLength:
|
||||||
await request.respond(Http400, "Bad Request. Content-Length does not match actual.")
|
await request.respond(Http400, "Bad Request. Content-Length does not match actual.")
|
||||||
return true
|
return true
|
||||||
|
elif hasChunkedEncoding(request):
|
||||||
|
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding
|
||||||
|
var sizeOrData = 0
|
||||||
|
var bytesToRead = 0
|
||||||
|
request.body = ""
|
||||||
|
|
||||||
|
while true:
|
||||||
|
lineFut.mget.setLen(0)
|
||||||
|
lineFut.clean()
|
||||||
|
|
||||||
|
# The encoding format alternates between specifying a number of bytes to read
|
||||||
|
# and the data to be read, of the previously specified size
|
||||||
|
if sizeOrData mod 2 == 0:
|
||||||
|
# Expect a number of chars to read
|
||||||
|
await client.recvLineInto(lineFut, maxLength = maxLine)
|
||||||
|
try:
|
||||||
|
bytesToRead = lineFut.mget.parseHexInt
|
||||||
|
except ValueError:
|
||||||
|
# Malformed request
|
||||||
|
await request.respond(Http411, ("Invalid chunked transfer encoding - " &
|
||||||
|
"chunk data size must be hex encoded"))
|
||||||
|
return true
|
||||||
|
else:
|
||||||
|
if bytesToRead == 0:
|
||||||
|
# Done reading chunked data
|
||||||
|
break
|
||||||
|
|
||||||
|
# Read bytesToRead and add to body
|
||||||
|
# Note we add +2 because the line must be terminated by \r\n
|
||||||
|
let chunk = await client.recv(bytesToRead + 2)
|
||||||
|
request.body = request.body & chunk
|
||||||
|
|
||||||
|
inc sizeOrData
|
||||||
elif request.reqMethod == HttpPost:
|
elif request.reqMethod == HttpPost:
|
||||||
await request.respond(Http411, "Content-Length required.")
|
await request.respond(Http411, "Content-Length required.")
|
||||||
return true
|
return true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue