Configuration
The third argument to http.Server(App).init is an
http.ServerConfig. Every field has a default, so you only set
the ones you want to change:
var server = http.Server(void).init(init.gpa, init.io, .{
.listeners = &.{.{
.address = .{ .ip = try std.Io.net.IpAddress.parse("0.0.0.0", 8080) },
}},
.timeout = .{ .request = .fromSeconds(60) },
.request = .{ .max_body_size = 10 * 1024 * 1024 },
}, {});
This server listens on port 8080 on all interfaces, gives each request 60 seconds, and accepts bodies up to 10 MiB.
Listeners
listeners is the list of addresses the server accepts connections on. If you don't set it, the
server listens on 127.0.0.1:8080. One server can listen on several addresses, with TLS on some of
them:
var server = http.Server(void).init(init.gpa, init.io, .{
.listeners = &.{
.{
.address = .{ .ip = try std.Io.net.IpAddress.parse("0.0.0.0", 8443) },
.tls = .{ .certificate = .{ .file = .{
.cert_path = "examples/certs/cert.pem",
.key_path = "examples/certs/key.pem",
} } },
},
.{
.address = .{ .ip = try std.Io.net.IpAddress.parse("0.0.0.0", 8080) },
},
.{
.address = .{ .unix = try std.Io.net.UnixAddress.init("/tmp/app.sock") },
},
},
}, {});
This server accepts HTTPS on port 8443, plain HTTP on port 8080, and plain HTTP on a Unix socket.
req.secure tells a handler whether the request came over TLS.
TLS
A listener with .tls set serves only TLS. The certificate and key are PEM files, with the
certificate chain leaf first. The key has to be PKCS#8 or an EC key, and it can't have a passphrase.
They are loaded when the server starts. .bytes instead of .file takes them from memory.
.client_auth asks clients for a certificate and checks it against the authorities in .ca:
.tls = .{
.certificate = .{ .file = .{ .cert_path = "cert.pem", .key_path = "key.pem" } },
.client_auth = .{ .ca = .{ .file = .{ .path = "clients-ca.pem" } } },
},
Clients without a valid certificate can't connect. With .mode = .request, clients that don't send
one are let in too.
See http.Listener for the other listener options.
Timeouts
| Field | Default | Description |
|---|---|---|
timeout.request |
30 s | Time to read the request and send the response, handler included |
timeout.keepalive |
30 s | How long an idle connection is kept open |
timeout.request_count |
none | How many requests one connection can make |
timeout.shutdown |
30 s | How long a graceful shutdown waits for open connections |
null turns a timeout off. A handler can change its own request timeout with req.setTimeout.
Limits
| Field | Default | Description |
|---|---|---|
max_connections |
10,000 | Most connections open at once |
request.max_body_size |
1 MiB | Largest request body |
request.buffer_size |
16 KiB | Largest request line and headers, together |
request.max_header_count |
64 | Most headers in a request |
request.max_query_count |
32 | Most query parameters |
request.max_form_count |
32 | Most form fields |
request.max_multiform_count |
32 | Most multipart fields |
A body over max_body_size gets 413. A request with too many headers gets 431. At
max_connections, the server stops accepting connections until one closes.
Behind a Proxy
Behind a reverse proxy, the socket peer is the proxy. Set trusted_proxy_hops to the number of
proxies in front of the server. req.remote_address then comes from the X-Forwarded-For header.
Only set it when clients can't reach the server except through the proxies. Otherwise they can put
any address they want in the header.
Next Steps
- Deployment covers running the server in production.