🔗Requests
Inside your handler you receive an HttpRequest (req). It is a lazy, parsed view of the HTTP request: accessors materialize strings on demand, and the body is available either fully-buffered or as a stream.
See also parser for how requests are produced, and server for the handler/response side.
🔗Request line
req.getMethod() # HttpMethod (HttpGet, HttpPost, …)
req.getPath() # lent string e.g. "/api/items/42"
req.getQuery() # lent string raw query string "name=bob&age=4"
req.getUrl() # lent string path + query
req.getClientIp() # stringRouting is done with case/if on getPath() — the examples use case req.getMethod() then compare path. getPath()/getQuery()/getUrl()return lent string zero-copy views of the parser buffer.
🔗Headers
let headers = req.getHeaders() # HttpHeaders
headers.getOrDefault("Content-Type", @["application/octet-stream"].HttpHeaderValues)
headers.getOrDefault("Cookie")
req.getContentLength() # int, or -1 / 0 when absent
req.getConnectionClose() # bool — "Connection: close"🔗Body: buffered
For small bodies, read everything:
let bytes = req.getBody() # seq[byte]
let text = req.getBodyString() # string
req.bodyView() # (data: ptr UncheckedArray[byte], len: int)🔗Body: streaming
getBodyStream returns a BodyStream you can consume in bounded chunks — the memory-efficient path for large or hostile payloads. All methods take a maxLen bound and never allocate more than asked.
var stream = req.getBodyStream()
while true:
let chunk = stream.readChunk(64 * 1024) # seq[byte]
if chunk.len == 0: break
# process chunk...
# alternatives:
stream.readChunkString(maxLen) # string
stream.peekChunk(maxLen) # (data, len) without consuming
stream.drainChunk(len) # consume after peeking
stream.readChunkInto(buf, maxLen) # reuse a seq
stream.peekAll() # (data, len) full remaining viewreadChunk(maxLen)/peekChunk(maxLen) never return more than maxLen bytes, so streaming stays bounded even with maxBodySize = 0.
🔗Multipart / file uploads
let mp = req.getMultipart(tmpDir = "") # MultipartStreamerRef
let tmpFile = req.streamToFile(tmpDir = "") # string — path to the temp filestreamToFile streams the raw body straight to a temp file (zero buffering). See multipart.
🔗Chunked / pipelining notes
The parser handles Transfer-Encoding: chunked internally; req.getBody() / streaming reads see the decoded body. Pipelined requests are processed in order by the server.
🔗API reference
Full signatures: HTTP parser API. Related: server, multipart.