Getting started
Install#
# serve.nimble
requires "serve"Or add it directly to an existing project's .nimble file alongside your other dependencies.
Your first server#
The simplest possible server is a function from Request to Response:
import serve
serve(8080, proc(req: Request): Response {.closure.} =
ok("hello"))Run it, then:
curl http://127.0.0.1:8080/
# helloThat's the whole contract: read req, return a Response. No middleware chain to configure, no framework runtime underneath.
Serving static files#
Drop in the built-in static handler instead of writing your own:
import serve
serve(8080, staticHandler("./public"))staticHandler includes path-traversal safety by default — a request for ../../etc/passwd is rejected before it touches the filesystem.
What you get for free#
Every server built on serve, sync or async, inherits the same protections without extra configuration:
Keep-alive
Connections stay open across requests by default, following HTTP/1.1 semantics.
Request-size caps
Oversized request bodies are rejected with 413 before they're fully buffered.
Streamed responses
Response bodies stream to the client — no truncation on large payloads.
Slowloris guard
Connections that trickle bytes in slowly to exhaust server resources are detected and closed.
Next step#
The example above is synchronous — one request at a time. For concurrent connections, TLS, HTTP/2 or HTTP/3, move to the reactor, the async scheduler the rest of this stack rides on.
