Skip to main content

ServerSection

Struct ServerSection 

Source
pub struct ServerSection {
Show 19 fields pub host: String, pub port: u16, pub max_body_bytes: usize, pub request_timeout_ms: u64, pub header_read_timeout_ms: u64, pub max_headers: usize, pub max_path_segments: usize, pub ws_max_frame_bytes: usize, pub keep_alive_ms: u64, pub backlog: u32, pub shutdown_timeout_ms: u64, pub ws_max_message_bytes: usize, pub path_policy: PathPolicy, pub h2_max_header_list_size: u32, pub h2_max_concurrent_streams: u32, pub ws_idle_timeout_ms: u64, pub max_connections: usize, pub max_tls_handshakes: usize, pub tls_handshake_timeout_ms: u64,
}
Expand description

The [server] configuration table.

Every field has a default (see ServerSection::default), so a partial [server] table is valid.

Fields§

§host: String

Bind address host (default "127.0.0.1").

§port: u16

Bind port (default 8080).

§max_body_bytes: usize

Maximum accepted request body size in bytes (default 1 MiB). Larger bodies are rejected with 413 Payload Too Large.

A body whose Content-Length exceeds this is refused before the request is dispatched, so a handler that never reads the body cannot serve one anyway. A chunked body declares no length, so it is bounded as it is read — which means a handler that ignores a chunked body will not notice the cap. Reject on Transfer-Encoding explicitly if that matters.

Raise request_timeout_ms alongside it: the per-request timeout spans the upload, so a generous size cap paired with a short timeout rejects large-but-legitimate transfers part-way through.

§request_timeout_ms: u64

Per-request timeout in milliseconds (default 30000). 0 disables the timeout.

It bounds the whole exchange, including reading the request body. Bodies stream, so they are read inside the handler rather than before it, and a slow upload consumes this budget however small it is. Raising max_body_bytes therefore means raising this in step: a 100 MiB cap with a 30-second timeout rejects any client slower than ~3.4 MiB/s, mid-transfer, with 408.

§header_read_timeout_ms: u64

How long a connection may take to send its complete header block, in milliseconds (default 10000). 0 disables it.

This is the slow-loris defence: without it a client can hold a connection open indefinitely by dribbling one header byte at a time, because the per-request timeout does not start until there is a request.

It covers all three phases of a connection, by different means.

Before either protocol exists, the server is still reading up to the 24 bytes of the HTTP/2 preface to find out which one to speak, and neither mechanism below has been created yet. A connection that does not get as far as choosing a protocol within this deadline is closed — which is what bounds a peer that connects and then sends nothing at all.

HTTP/1 then gets a literal deadline on the header block. HTTP/2 has no equivalent — a header block arrives as frames on an already-open connection — so the same value drives a keep-alive PING and the deadline for its acknowledgement, which answers the equivalent question of whether the peer is still there. A stalled h2 peer is therefore dropped within roughly twice this value, and a live one with nothing to say answers the ping and stays: once a protocol has been negotiated this deadline no longer applies, so an idle-but-responsive client is not bound by it.

§max_headers: usize

Maximum number of headers accepted on a request (default 100).

§max_path_segments: usize

Maximum path segments accepted before a request is rejected with 414 (default 64).

The router walks segments recursively with backtracking, so path depth is a stack-depth question. hyper bounds the request line, which bounds this in practice, but the bound should be Churust’s own and stated rather than inherited by accident.

§ws_max_frame_bytes: usize

Maximum WebSocket frame size in bytes (default 1 MiB). Requires the ws feature.

§keep_alive_ms: u64

How long an idle connection is kept open for reuse, in milliseconds (default 75000). 0 disables keep-alive: answer and close.

Idle means no request in flight — a handler slower than this is busy, not idle, and its connection is left alone. The timer restarts when a request finishes.

§backlog: u32

Listen backlog: connections the kernel may queue before the accept loop reaches them (default 1024).

§shutdown_timeout_ms: u64

How long graceful shutdown waits for in-flight requests to finish, in milliseconds (default 30000). 0 waits indefinitely.

Without a bound, one slow request delays shutdown forever, which in a container means being killed rather than exiting cleanly.

§ws_max_message_bytes: usize

Maximum reassembled WebSocket message size in bytes (default 4 MiB). Requires the ws feature.

Separate from the frame cap because a peer can send many small continuation frames that reassemble into one enormous message.

§path_policy: PathPolicy

What to do with a non-canonical path spelling (default "strict").

One of "strict", "redirect" or "collapse". See PathPolicy.

§h2_max_header_list_size: u32

Maximum size of a received HTTP/2 header block, in bytes (default 16384).

The HTTP/2 counterpart of max_headers, which configures HTTP/1 only: h2 has no header count, it has an encoded size. Exceeding it is refused at the protocol level.

§h2_max_concurrent_streams: u32

Maximum concurrent HTTP/2 streams per connection (default 200). 0 removes the limit.

One h2 connection multiplexes many requests, so without this a single connection is an unbounded amount of concurrent work — the shape behind the HTTP/2 stream-flood denial-of-service family. hyper’s own docs encourage setting an explicit limit rather than inheriting its default.

§ws_idle_timeout_ms: u64

How long an upgraded WebSocket may sit with no traffic in either direction before it is closed, in milliseconds (default 300000, five minutes). 0 disables the bound. Requires the ws feature.

An upgraded socket holds a connection permit for its whole life, and none of the HTTP-level bounds survive the upgrade — header_read_timeout_ms applies before there is a WebSocket and request_timeout_ms wraps a request that has already completed. Without this, a peer that completes the handshake and then says nothing pins a permit until the process restarts.

§max_connections: usize

Maximum simultaneously served connections (default 25000). 0 means unlimited.

The backlog bounds what the kernel queues; this bounds what the process accepts. Without it, memory and file descriptors are limited only by what the OS will hand out, and the failure mode is the whole process dying rather than new connections waiting.

§max_tls_handshakes: usize

Maximum TLS handshakes in progress at once (default 256). 0 means unlimited. Requires the tls feature.

Much smaller than max_connections on purpose: a handshake is asymmetric work — cheap to ask for, expensive to answer — so it needs its own, tighter bound.

§tls_handshake_timeout_ms: u64

How long a TLS handshake may take before the connection is dropped, in milliseconds (default 10000). 0 disables the bound.

header_read_timeout_ms cannot cover this: before the handshake completes there is no HTTP layer to time out. Without it, a client that completes the TCP handshake and then sends one byte per minute holds a connection open indefinitely.

The clock starts when the connection is accepted, so it covers waiting for a max_tls_handshakes permit as well as the handshake itself. That is what makes it a bound on how long a peer can hold a connection permit: timing only the handshake would let a queue of stalled peers expire a permit’s worth at a time while the rest waited unbounded. A consequence worth knowing is that under genuine handshake overload a legitimate client can be dropped while still queued — the alternative is holding its connection slot instead.

Trait Implementations§

Source§

impl Clone for ServerSection

Source§

fn clone(&self) -> ServerSection

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ServerSection

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ServerSection

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for ServerSection

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more