server
import std::net::http::server; · source
Types
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.
Properties
| Property | Type | Notes |
|---|---|---|
addr | SocketAddr | |
router | Router* | Non-null when built with with_router. Takes priority over handler. Owned by the caller; the Router must outlive this server. |
read_timeout_secs | i64 | Deadline applied to each request read (whole seconds). Zero disables; defaults to DEFAULT_READ_TIMEOUT_SECS. |
Constructors
static new(addr: SocketAddr, handler: (Request) -> Response) -> HttpServer;
static new(addr: SocketAddr, handler: (Request) -> Response) -> HttpServer;Build a server with a raw handler function. The handler receives every request and must produce a Response; all routing logic lives inside the handler.
static with_router(addr: SocketAddr, router: mut &Router) -> HttpServer;
static with_router(addr: SocketAddr, router: mut &Router) -> HttpServer;Build a server backed by a Router. Pass &router; the router must outlive the server (declare both in the same scope).
Methods
handler: Option<(Request) -> Response>;
handler: Option<(Request) -> Response>;Set when built with new. None when using a Router.
on_ready: Option<() -> void>;
with_ready(mut &this, cb: () -> void) -> &HttpServer;
with_ready(mut &this, cb: () -> void) -> &HttpServer;Attach a ready callback and return this for chaining. cb is called once after the socket binds successfully, before the first accept. Use it to log the listening address, write a pid-file, or signal an external health-check.
with_read_timeout(mut &this, secs: i64) -> &HttpServer;
with_read_timeout(mut &this, secs: i64) -> &HttpServer;Override the per-connection read timeout. secs == 0 disables; the default is DEFAULT_READ_TIMEOUT_SECS.
async run(mut &this) -> Result<(), IoError>;
async run(mut &this) -> Result<(), IoError>;Bind to this.addr and serve requests forever. Returns Err only on a fatal listener error (e.g. EMFILE, ENFILE).
async run_on(mut &this, listener: TcpListener) -> Result<(), IoError>;
async run_on(mut &this, listener: TcpListener) -> Result<(), IoError>;Serve on a listener the caller already bound, which is the form to reach for when the port matters and this.addr cannot name it: bind to port 0, read the assigned port off local_addr, then hand the listener over. Binding here and reporting the port afterwards would mean racing another process for the port in between.
dispatch(&this, req: Request) -> Response;
dispatch(&this, req: Request) -> Response;Route req to the router (if set) or the raw handler. Consumes the request regardless of which path is taken.
async serve_connection(mut &this, conn: BufStream<TcpStream>) -> void;
async serve_connection(mut &this, conn: BufStream<TcpStream>) -> void;Serve requests on conn until the client (or this server) signals close, a read exceeds the cap, or MAX_REQUESTS_PER_CONNECTION is reached. A parse failure on the FIRST request writes a canned 400; failures on follow-up requests are taken as "peer gave up" and close silently. Write failures (peer gone) end the connection. The accept loop always continues.
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.
Constants
const MAX_REQUESTS_PER_CONNECTION: u64 = 100;
const DEFAULT_READ_TIMEOUT_SECS: i64 = 30;type struct Name { ... }
type enum Name { ... }
type trait Name { ... }
type union Name { ... }Begins a type declaration; the keyword that follows says which kind. On its own, type Name = Existing; declares an alias.
type struct Name {
field: Type;
method(&this) -> Ret { ... }
}A value type with named fields and optional methods. Structs live on the stack and are passed by value. Fields are public by default and may carry = default values; methods take their receiver as &this, mut &this, or this.
type struct HttpServer {
addr: SocketAddr;
router: Router*;
read_timeout_secs: i64;
}A configured HTTP server ready to bind and run.
HttpServer.addr: SocketAddrHttpServer::handler: Option<(Request) -> Response>Set when built with new. None when using a Router.
type struct Request {
method: Method;
path: String;
version: String;
headers: Headers;
body: Array<u8>;
params: HashMap<String, String>;
}HTTP request.
std::net::http::requesttype struct Response {
status: StatusCode;
version: String;
headers: Headers;
body: Array<u8>;
}HTTP response.
std::net::http::responseHttpServer.router: Router*Non-null when built with with_router. Takes priority over handler. Owned by the caller; the Router must outlive this server.
type struct Router {
routes: Array<Route>;
}Method- and path-based request dispatcher.
std::net::http::routerHttpServer::on_ready: Option<() -> void>HttpServer.read_timeout_secs: i64Deadline applied to each request read (whole seconds). Zero disables; defaults to DEFAULT_READ_TIMEOUT_SECS.
static name(param: Type) -> Ret { ... }A method that belongs to the type rather than an instance, called as Type::name(..). For structs, static new(..) returning a struct literal is the idiomatic constructor.
static HttpServer::new(addr: SocketAddr, handler: (Request) -> Response) -> HttpServerBuild a server with a raw handler function. The handler receives every request and must produce a Response; all routing logic lives inside the handler.
(parameter) addr: SocketAddr(parameter) handler: (Request) -> Responsetype struct HttpServer {
addr: SocketAddr;
router: Router*;
read_timeout_secs: i64;
}A configured HTTP server ready to bind and run.
std::net::http::serverstatic HttpServer::with_router(addr: SocketAddr, router: mut &Router) -> HttpServerBuild a server backed by a Router. Pass &router; the router must outlive the server (declare both in the same scope).
(parameter) router: mut &Routermut &this
mut &TypeAn exclusive, mutating borrow. As a receiver, mut &this lets the method modify the fields - and callers can see that from the signature alone. As a parameter type, mut &T lets the callee mutate through the reference while the caller keeps ownership.
HttpServer::with_ready(mut &this, cb: () -> void) -> &HttpServerAttach a ready callback and return this for chaining. cb is called once after the socket binds successfully, before the first accept. Use it to log the listening address, write a pid-file, or signal an external health-check.
&this
mut &this
thisThe receiver of a method. Its first parameter declares how the method takes it: &this borrows read-only, mut &this borrows exclusively, and this / mut this move the value in and consume it. In the body, this.field reaches the members.
(parameter) cb: () -> voidHttpServer::with_read_timeout(mut &this, secs: i64) -> &HttpServerOverride the per-connection read timeout. secs == 0 disables; the default is DEFAULT_READ_TIMEOUT_SECS.
(parameter) secs: i64async function name(param: Type) -> T { ... }Compiles the function into a stackless state machine. Calling it builds a future whose output is the declared return type; nothing runs until that future is polled. Allowed on free functions, methods, and trait methods.
language referenceasync HttpServer::run(mut &this) -> Result<(), IoError>Bind to this.addr and serve requests forever. Returns Err only on a fatal listener error (e.g. EMFILE, ENFILE).
primitive ()The unit type: a value that carries no information, and the empty tuple. Distinct from void, which is the absence of a value - Result<(), E> succeeds with nothing to return. 0 bytes.
type struct IoError {
kind: IoErrorKind;
os_code: i32;
}async HttpServer::run_on(mut &this, listener: TcpListener) -> Result<(), IoError>Serve on a listener the caller already bound, which is the form to reach for when the port matters and this.addr cannot name it: bind to port 0, read the assigned port off local_addr, then hand the listener over.
(parameter) listener: TcpListenertype struct TcpListener {
fd: i32;
}HttpServer::dispatch(&this, req: Request) -> ResponseRoute req to the router (if set) or the raw handler. Consumes the request regardless of which path is taken.
(parameter) req: Requestasync HttpServer::serve_connection(mut &this, conn: BufStream<TcpStream>) -> voidServe requests on conn until the client (or this server) signals close, a read exceeds the cap, or MAX_REQUESTS_PER_CONNECTION is reached. A parse failure on the FIRST request writes a canned 400; failures on follow-up requests are taken as "peer gave up" and close silently.
(parameter) conn: BufStream<TcpStream>type struct BufStream<S> {
inner: S;
rbuf: Array<u8>;
rpos: u64;
scratch: Array<u8>;
wbuf: Array<u8>;
}type struct TcpStream {
fd: i32;
}mut name: Type = value;A mutable binding, reassignable after declaration - mutability is opt-in, const is the default. At module level it declares mutable global state. Before & it marks an exclusive reference or receiver instead.
mut server: HttpServerstatic HttpServer::with_router(addr: SocketAddr, router: mut &Router) -> HttpServerBuild a server backed by a Router. Pass &router; the router must outlive the server (declare both in the same scope).
mut ex: Executortype struct Executor {
inner: ExecInner*;
worker_tids: [u64];
}A multi-threaded, poll-driven task executor. Construct one, spawn futures onto it (keeping the JoinHandle to await a result, or dropping it to fire-and-forget), and block_on to drive a root future to its value. A pool of worker threads does all polling; the calling thread only ever blocks on a completion condvar.
static Executor::new() -> ExecutorCreate an executor whose pool is sized to the hardware parallelism.
std::future::executormut ex: ExecutorExecutor::block_on<F, O>(mut &this, root: F) -> O
where F: Future<O>Spawn root and block the calling thread until a worker drives it to completion, then return its value. Panics if root was cancelled or could not complete; use spawn(root).join() for the Result.
mut server: HttpServerasync HttpServer::run(mut &this) -> Result<(), IoError>Bind to this.addr and serve requests forever. Returns Err only on a fatal listener error (e.g. EMFILE, ENFILE).
const NAME: Type = value;At module level, a true compile-time constant, conventionally SCREAMING_SNAKE_CASE. (mut at module level declares mutable global state instead.)
const MAX_REQUESTS_PER_CONNECTION: u64 = 100;const DEFAULT_READ_TIMEOUT_SECS: i64 = 30;import a::b;
import a::b::{ X, Y };
import a::b as c;
import a::b::*;Brings a module, or selected items from it, into scope. One path per declaration: use the brace form for several items, as to alias, and * for everything public (prefer the brace form; wildcards invite name collisions).
namespace std::net::http::server;HTTP server: non-blocking, one connection at a time, HTTP/1.1 keep-alive within a connection.
module pagestatic HttpServer::new(addr: SocketAddr, handler: (Request) -> Response) -> HttpServerBuild a server with a raw handler function. The handler receives every request and must produce a Response; all routing logic lives inside the handler.
HttpServer.addr: SocketAddrHttpServer::handler: Option<(Request) -> Response>Set when built with new. None when using a Router.
HttpServer.router: Router*Non-null when built with with_router. Takes priority over handler. Owned by the caller; the Router must outlive this server.
HttpServer::with_ready(mut &this, cb: () -> void) -> &HttpServerAttach a ready callback and return this for chaining. cb is called once after the socket binds successfully, before the first accept. Use it to log the listening address, write a pid-file, or signal an external health-check.
HttpServer::with_read_timeout(mut &this, secs: i64) -> &HttpServerOverride the per-connection read timeout. secs == 0 disables; the default is DEFAULT_READ_TIMEOUT_SECS.
async HttpServer::run_on(mut &this, listener: TcpListener) -> Result<(), IoError>Serve on a listener the caller already bound, which is the form to reach for when the port matters and this.addr cannot name it: bind to port 0, read the assigned port off local_addr, then hand the listener over.
async HttpServer::serve_connection(mut &this, conn: BufStream<TcpStream>) -> voidServe requests on conn until the client (or this server) signals close, a read exceeds the cap, or MAX_REQUESTS_PER_CONNECTION is reached. A parse failure on the FIRST request writes a canned 400; failures on follow-up requests are taken as "peer gave up" and close silently.
HttpServer.read_timeout_secs: i64Deadline applied to each request read (whole seconds). Zero disables; defaults to DEFAULT_READ_TIMEOUT_SECS.
const DEFAULT_READ_TIMEOUT_SECS: i64 = 30;new T { field: value }
new E::Variant(args)
new T[n]Heap allocation. new T { .. } places a struct literal on the heap and yields a T*, and new E::V(args) does the same for an enum variant; new T[n] reserves n uninitialised T - the typed malloc. The storage comes from T's Allocate implementation, or else the global allocator. Parentheses after a struct's name are refused (E0117): there are no constructors, and a struct's static new(..) is an ordinary method.
Option::NoneHttpServer::on_ready: Option<() -> void>Result::Err(E)HttpServer::dispatch(&this, req: Request) -> ResponseRoute req to the router (if set) or the raw handler. Consumes the request regardless of which path is taken.
const MAX_REQUESTS_PER_CONNECTION: u64 = 100;