serve — HTTP/1.1 + HTTP/2 server

Repo → aoughwl/serve Reference

The top of the stack. Pass a handler proc(req: Request): Response {.closure.} and return whatever Response you like, or drop in staticHandler(root). A ServerConn transport shim makes the request-read / response-write core transport-independent, so HTTP and HTTPS share it byte-for-byte.

import serve
proc hello(req: Request): Response {.closure.} =
  response(200, "text/plain", "hi " & req.path & "\n")
serve(8080, hello)                       # HTTP/1.1
serveTls(8443, "cert.pem", "key.pem", hello)   # HTTPS
Capability Behavior
Programmable / static serve(port, handler); serve(root, port) static files
HTTPS serveTls(port, cert, key, handler) — one TLS session per connection
Concurrency serveConcurrent / serveTlsConcurrent — a pool of worker threads all accept() one shared socket
HTTP/2 import serve/http2: serveHttp2 (h2c) and serveHttp2Tls (ALPN “h2”, the browser path) over nghttp2
Request framing Content-Length and Transfer-Encoding: chunked (de-chunked in place)
Expect: 100-continue interim 100 Continue before the body is read
Compression opt-in compressResponse(req, resp) (serve/encoding) — negotiates Accept-Encoding, gzip/br-encodes
Hardening 8 MB request cap → 413, 15 s slowloris read timeout, keep-alive, HEAD, ..403

The concurrent pool and HTTP/2 use {.nimcall.} handlers (NimcallHandler) rather than closures — a bare function pointer crosses thread and C-callback boundaries where a captured closure does not. HTTP/3 serving would need a QUIC stack (none installed); the requests client already speaks HTTP/3.


Back to top

aoughwl — next-gen self-hosted platform for things n stuff. Reach out on Discord (timbuktu_guy) for access to the private backends.

This site uses Just the Docs, a documentation theme for Jekyll.