http.server
import http.server
httplifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelledhttp.server.*needsimport http.server.
HttpServer: the server end of the module.
It accepts connections, speaks HTTP/1.1 or HTTP/2 as negotiated, runs the middleware chain around the matched handler, and serves static files when configured to. It can run single-threaded or hand connections to a pool of workers.
Classes
HttpServer
class http.HttpServer
An HTTP/1.1 server.
import http
var server = http.server(3000)
server.get('/', @(request, response) {
response.html('<h1>Hello</h1>')
})
server.get('/users/:id', @(request, response) {
response.json({ id: request.param('id') })
})
server.listen()
The pieces a server put in front of an application usually provides are
here rather than assumed: TLS with use_tls(), static files with
serve_files(), response compression, byte ranges, conditional
requests, keep-alive with bounded reuse, and limits on every part of a
request that a peer controls the size of.
- printable — has a
@to_string(), soechoandprint()show something useful
Fields
| Field | Type | Description |
|---|---|---|
host | string | The address to bind to. |
port | number | The port to bind to. |
read_timeout | number | How long to wait for a request to arrive, in milliseconds. |
write_timeout | number | How long a write may block before the client is treated as gone. |
keep_alive_timeout | number | How long an idle keep-alive connection is held open, in milliseconds. |
max_keep_alive_requests | number | The most requests one connection may serve before it is closed. |
max_line_size | number | The longest request line, in bytes. |
max_header_size | number | The largest header section, in bytes. |
max_header_count | number | The most header fields one request may carry. |
header_timeout | number | How long the whole request head may take to arrive, in seconds, once its first byte has. |
max_body_size | number | The largest request body accepted, in bytes. |
server_name | string | The value sent in the Server header. |
compression | bool | Whether to compress responses whose media type benefits from it and whose client asked for it. |
compression_min_size | number | The smallest response worth compressing, in bytes. |
compression_quality | ?number | How hard to compress, on the scale of whichever coding content negotiation lands on - brotli 0-11,… |
trust_proxy | bool | Whether HttpRequest.client_ip() should consult forwarding headers. |
trusted_proxies | list | The proxy addresses to skip when walking a forwarding chain. |
socket | ?TcpStream | The listening socket, once listen() has bound it. |
http2 | bool | Whether to speak HTTP/2 when a client asks for it - through ALPN on a TLS connection, or through the… |
Constructor
http.HttpServer(port: ?number, host: ?string)
Parameters
port(?number) — defaults to8000host(?string) — defaults to'127.0.0.1'
HttpServer.handle()
http.HttpServer.handle(method: string, pattern: string, handler, name: ?string)
Registers handler for method requests matching pattern.
See Router for what a pattern may contain: literal segments, :name
parameters, and a trailing catch-all.
Parameters
method(string)pattern(string)handler(function(2)) — called with the request and responsename(?string) — a route name, forurl_for()
Returns — HttpServer: this same instance, for chaining
HttpServer.get()
http.HttpServer.get(pattern: string, handler, name: ?string)
Registers a GET handler. A HEAD request for the same path is answered by it too, with the body dropped.
Parameters
pattern(string)handler(function(2))name(?string)
Returns — HttpServer: this same instance, for chaining
HttpServer.post()
http.HttpServer.post(pattern: string, handler, name: ?string)
Registers a POST handler.
Parameters
pattern(string)handler(function(2))name(?string)
Returns — HttpServer: this same instance, for chaining
HttpServer.put()
http.HttpServer.put(pattern: string, handler, name: ?string)
Registers a PUT handler.
Parameters
pattern(string)handler(function(2))name(?string)
Returns — HttpServer: this same instance, for chaining
HttpServer.patch()
http.HttpServer.patch(pattern: string, handler, name: ?string)
Registers a PATCH handler.
Parameters
pattern(string)handler(function(2))name(?string)
Returns — HttpServer: this same instance, for chaining
HttpServer.delete()
http.HttpServer.delete(pattern: string, handler, name: ?string)
Registers a DELETE handler.
Parameters
pattern(string)handler(function(2))name(?string)
Returns — HttpServer: this same instance, for chaining
HttpServer.options()
http.HttpServer.options(pattern: string, handler, name: ?string)
Registers an OPTIONS handler, replacing the automatic one for this path.
Parameters
pattern(string)handler(function(2))name(?string)
Returns — HttpServer: this same instance, for chaining
HttpServer.head()
http.HttpServer.head(pattern: string, handler, name: ?string)
Registers a HEAD handler, replacing the automatic GET fallback for this path.
Parameters
pattern(string)handler(function(2))name(?string)
Returns — HttpServer: this same instance, for chaining
HttpServer.any()
http.HttpServer.any(pattern: string, handler)
Registers one handler for every method a route can carry.
Parameters
pattern(string)handler(function(2))
Returns — HttpServer: this same instance, for chaining
HttpServer.use()
http.HttpServer.use(middleware)
Adds a middleware, called for every request before the route handler.
A middleware takes (request, response, next) and must call next() to
let the rest of the chain run; not calling it is how a middleware
short-circuits, which is exactly what an authentication or rate-limiting
layer wants to do.
server.use(@(request, response, next) {
var started = time()
next()
echo '${request.method} ${request.path} ${response.status} ' +
'${(time() - started) * 1000}ms'
})
Middleware run in the order they were added, outermost first.
Parameters
middleware(function(3))
Returns — HttpServer: this same instance, for chaining
HttpServer.not_found()
http.HttpServer.not_found(handler)
Sets the handler called when no route matches. The default sends a plain
404, or a JSON one when the client asked for JSON.
Parameters
handler(function(2))
Returns — HttpServer: this same instance, for chaining
HttpServer.error_handler()
http.HttpServer.error_handler(handler)
Sets the handler called when a route handler raises.
It takes (request, response, error) and is responsible for producing
the response. Without one, the server sends a bare 500 and reports the
error through on_error() listeners - it never puts an exception
message in a response body, since that is how internal paths and query
fragments end up on a user’s screen.
Parameters
handler(function(3))
Returns — HttpServer: this same instance, for chaining
HttpServer.serve_files()
http.HttpServer.serve_files(prefix: string, directory: string, options: ?dict)
Serves the files under directory at URLs beginning with prefix.
server.serve_files('/static', './public', { cache_age: 86400 })
Parameters
prefix(string)directory(string)options(?dict) — passed through toStaticFiles-index_files,cache_age,etag,precompressed,allow_dotfiles,fallback
Returns — HttpServer: this same instance, for chaining
HttpServer.routes()
http.HttpServer.routes() -> Router
The router, for anything the convenience methods above do not cover - listing routes, or building a URL from a route name.
Returns Router
HttpServer.on_connect()
http.HttpServer.on_connect(listener)
Adds a listener called with the Connection each time a client
connects.
Parameters
listener(function(1))
Returns — HttpServer: this same instance, for chaining
HttpServer.on_disconnect()
http.HttpServer.on_disconnect(listener)
Adds a listener called with the Connection when a client disconnects.
Parameters
listener(function(1))
Returns — HttpServer: this same instance, for chaining
HttpServer.on_receive()
http.HttpServer.on_receive(listener)
Adds a listener called with (request, response) after a request has
been parsed and before it is routed.
Parameters
listener(function(2))
Returns — HttpServer: this same instance, for chaining
HttpServer.on_reply()
http.HttpServer.on_reply(listener)
Adds a listener called with (request, response) after a response has
been sent. This is where an access log belongs.
Parameters
listener(function(2))
Returns — HttpServer: this same instance, for chaining
HttpServer.on_error()
http.HttpServer.on_error(listener)
Adds a listener called with (error, connection) whenever serving a
connection fails.
Without at least one such listener, connection-level errors are swallowed: one client sending a malformed request must not take the server down with it.
Parameters
listener(function(2))
Returns — HttpServer: this same instance, for chaining
HttpServer.use_tls()
http.HttpServer.use_tls(cert_chain: string, private_key: string, options: ?dict)
Turns on TLS, using the given PEM-encoded certificate chain and private key.
cert_chain must be the server certificate followed by any
intermediates - leaving the intermediates out is the single most common
TLS misconfiguration, and it fails only for the clients that do not
happen to have them cached.
Parameters
cert_chain(string) — PEM, leaf firstprivate_key(string) — PEMoptions(?dict) —alpn(a list of protocol names),client_ca(PEM roots for mutual TLS),require_client_cert,min_versionandmax_version
Returns — HttpServer: this same instance, for chaining
Note: The certificate and key are parsed when the first handshake runs, not here, so a malformed or mismatched pair surfaces as a failed connection rather than as a failed call to this method.
HttpServer.load_certs()
http.HttpServer.load_certs(cert_path: string, key_path: ?string, options: ?dict)
Loads the certificate and key from files rather than strings.
Parameters
cert_path(string)key_path(?string) — defaults tocert_path, for a combined PEM fileoptions(?dict) — asuse_tls()
Returns — HttpServer: this same instance, for chaining
HttpServer.set_tls_config()
http.HttpServer.set_tls_config(config)
Uses a net.tls.TlsConfig built elsewhere, for anything use_tls()
does not expose.
Parameters
config(TlsConfig)
Returns — HttpServer: this same instance, for chaining
HttpServer.is_secure()
http.HttpServer.is_secure() -> bool
Whether this server is configured to serve over TLS.
Returns bool
HttpServer.listen()
http.HttpServer.listen()
Binds the socket and serves connections until close() is called.
Connections are served one at a time on the calling thread. For a server
that uses more than one core, see http.serve(), which runs this same
request pipeline across a pool of isolates.
Raises HttpError if the socket cannot be bound
HttpServer.bind()
http.HttpServer.bind()
Binds and starts listening without accepting anything, so a caller can drive the accept loop itself.
The listener is left in non-blocking mode, since accept() and
listen() here go through a net.Acceptor. A caller driving its own
loop over socket directly gets nil from accept() whenever nothing
is waiting.
Raises HttpError if the socket cannot be bound
HttpServer.accept()
http.HttpServer.accept() -> ?TcpStream
Accepts one connection, blocking until one arrives. Only valid after
bind().
Returns nil if the server is stopped while this is waiting, since
there is then nothing left to wait for.
Returns ?TcpStream
HttpServer.address()
http.HttpServer.address() -> ?SocketAddr
The address the server is listening on. After binding to port 0, this
is how to discover the port that was actually chosen.
Returns ?SocketAddr
HttpServer.is_listening()
http.HttpServer.is_listening() -> bool
Whether the server is currently listening.
Returns bool
HttpServer.close()
http.HttpServer.close()
Stops the server and closes the listening socket. The accept loop reads
the stopped flag on its next round and ends, within one net.Acceptor
interval of this call.
HttpServer.serve_connection()
http.HttpServer.serve_connection(client)
Serves every request on one already-accepted client socket, then closes it.
This is the whole per-connection pipeline - TLS handshake, keep-alive
loop, parsing, dispatch, response - and is public so that a caller
running its own accept loop (or handing sockets to worker isolates) can
reuse it exactly as listen() does.
Parameters
client(TcpStream)
HttpServer.accept_connection()
http.HttpServer.accept_connection(client)
Turns an accepted socket into a Connection, running the TLS handshake
when one is configured and notifying on_connect() listeners.
Split out of serve_connection() so that a caller driving its own event
loop can take a connection on without also committing to serving it to
completion on the spot: see serve_next().
Parameters
client(TcpStream)
Returns — ?Connection: nil when the handshake failed, in which
case the socket has already been closed and the failure reported to
on_error() listeners
HttpServer.serve_next()
http.HttpServer.serve_next(connection, served: ?number)
Reads and answers exactly one request, and reports whether the connection may be used again.
This is the unit an event loop works in. _serve_requests() calls it in
a loop for one connection at a time, which is what listen() does; a
polled worker calls it once per connection that has actually become
readable, which is what lets one thread hold many connections at once.
Parameters
connection(Connection)served(?number) — how many requests this connection has already answered, so the keep-alive budget and the shorter idle read timeout apply from the second request onwards
Returns — bool: whether to keep the connection open
HttpServer.serve_http2()
http.HttpServer.serve_http2(connection)
Runs an HTTP/2 session on connection until the peer goes away.
Unlike HTTP/1.1, this owns the connection for its whole life: an HTTP/2 connection is already multiplexed internally, so the streams on it are interleaved even though the connection itself is not interleaved with any other.
Parameters
connection(Connection)
HttpServer.is_http2_connection()
http.HttpServer.is_http2_connection(connection) -> bool
Whether a connection that has just been taken on is going to speak HTTP/2. Reading this costs a peek at the first bytes on a cleartext connection, so it is asked once and the answer kept.
Parameters
connection(Connection)
Returns bool
HttpServer.report_error()
http.HttpServer.report_error(error, connection)
Hands error to this server’s on_error() listeners.
Public so that a caller running its own connection loop reports failures through the same listeners the built-in loops use, instead of inventing a second place errors can appear.
Parameters
error(Error)connection(?Connection)
HttpServer.finish_connection()
http.HttpServer.finish_connection(connection)
Notifies on_disconnect() listeners and closes the connection.
Parameters
connection(Connection)
HttpServer.handle_request()
http.HttpServer.handle_request(request, response) -> HttpResponse
Runs one already-parsed request through the middleware chain, the router and the error handling, and returns the response.
This is the whole application-facing half of the server, with no reference to how the request arrived. That is what lets the same routes and middleware serve an HTTP/1.1 connection and an HTTP/2 stream without either protocol knowing about the other.
Parameters
request(HttpRequest)response(?HttpResponse) — an existing response to fill in
Returns HttpResponse
HttpServer.to_string()
http.HttpServer.to_string()
2026, Richard Ore and Zuri contributors