Skip to content
CryoCryo home
Stdlibnet::http

server

import std::net::http::server; · source

HttpServer

type struct HttpServer {
    addr: SocketAddr;

    handler: Option<(Request) -> Response>;

    router: Router*;

    on_ready: Option<() -> void>;

    read_timeout_secs: i64;

    static new(addr: SocketAddr, handler: (Request) -> Response) -> HttpServer;
    static with_router(addr: SocketAddr, router: mut &Router) -> HttpServer;
    with_ready(mut &this, cb: () -> void) -> &HttpServer;
    with_read_timeout(mut &this, secs: i64) -> &HttpServer;
    async run(mut &this) -> Result<(), IoError>;
    async run_on(mut &this, listener: TcpListener) -> Result<(), IoError>;
    dispatch(&this, req: Request) -> Response;
    async serve_connection(mut &this, conn: BufStream<TcpStream>) -> void;
}
mut server: HttpServer = HttpServer::with_router(addr, &router);
mut ex: Executor = Executor::new();
ex.block_on(server.run());

run() is an async method and needs an Executor — its reactor is what the accept and the per-connection reads register with. Connections are still served one at a time: this layer is on the async transport, not yet concurrent across connections.

Two entry points. HttpServer::new(addr, handler) takes a raw function-pointer handler, with all routing and method checking inside it. HttpServer::with_router(addr, &router) delegates to a Router.

The router must outlive the server — declare both in the same scope. The server holds a pointer, not ownership.

with_ready(cb) attaches a callback invoked once after the socket binds and before the first accept: log the listening address, write a pid-file, signal a health check. with_read_timeout(secs) sets the per-request read deadline; zero disables it. A read that hits the cap is abandoned, and abandoning an in-flight read closes the connection — it is a hard close, not a recoverable error. Both return the server for chaining. run_on(listener) runs against a listener you already have, and serve_connection drives one already-accepted connection through keep-alive to close.

run() never completes normally, returning only on a fatal listener-level error such as EMFILE. Per-connection failures — parse errors, client hangups, write errors — are swallowed.

Keep-alive

Within a connection the server honours HTTP/1.1 persistence: after answering a request it reads the next one on the same socket until the client sends Connection: close, the read timeout fires, or the peer hangs up. Each request within the connection is still served sequentially — there is no pipelining.