I needed help to create a template and/or macro that would allow to read small
chunks of data from a http body stream in an elegant manner. My idea can be
seen in the following code:
### Replace this code block
### Begin
let chunkSize = 8*1024
var remainder = req.contentLength
while true:
let data = await req.client.recv(min(remainder, chunkSize))
echo data
remainder -= len(data)
if remainder == 0:
break
### End
### With this small piece of code
### Begin
for data in req.bodyStream(chunkSize):
echo data
### End
Run
All code:
import asynchttpserver, asyncdispatch
import asyncnet
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
let chunkSize = 8*1024
var remainder = req.contentLength
while true:
let data = await req.client.recv(min(remainder, chunkSize))
echo data
bodyLength += len(data)
remainder -= len(data)
if remainder == 0:
break
else:
bodyLength += req.body.len
await req.respond(Http200, htmlpage(contentLength, bodyLength))
let server = newAsyncHttpServer(maxBody = 10485760, stream = stream)
waitFor server.serve(Port(8080), cb)
Run