trillium_http/
http_config.rs

1#![allow(dead_code)]
2
3pub const DEFAULT_CONFIG: HttpConfig = HttpConfig {
4    response_buffer_len: 512,
5    request_buffer_initial_len: 128,
6    head_max_len: 8 * 1024,
7    max_headers: 128,
8    response_header_initial_capacity: 16,
9    copy_loops_per_yield: 16,
10    received_body_max_len: 500 * 1024 * 1024,
11    received_body_initial_len: 128,
12    received_body_max_preallocate: 1024 * 1024,
13};
14
15/**
16# Performance and security parameters for trillium-http.
17
18Trillium's http implementation is built with sensible defaults, but applications differ in usage and
19this escape hatch allows an application to be tuned. It is best to tune these parameters in context
20of realistic benchmarks for your application.
21
22Long term, trillium may export several standard defaults for different constraints and application
23types. In the distant future, these may turn into initial values and trillium will tune itself based
24on values seen at runtime.
25
26
27## Performance parameters
28
29### `response_buffer_len`
30
31The initial buffer allocated for the response. Ideally this would be exactly the length of the
32combined response headers and body, if the body is short. If the value is shorter than the headers
33plus the body, multiple transport writes will be performed, and if the value is longer, unnecessary
34memory will be allocated for each conn. Although a tcp packet can be up to 64kb, it is probably
35better to use a value less than 1.5kb.
36
37**Default**: `512`
38
39**Unit**: byte count
40
41### `request_buffer_initial_len`
42
43The initial buffer allocated for the request headers. Ideally this is the length of the request
44headers. It will grow nonlinearly until `max_head_len` or the end of the headers are reached,
45whichever happens first.
46
47**Default**: `128`
48
49**Unit**: byte count
50
51### `received_body_initial_len`
52
53The initial buffer capacity allocated when reading a chunked http body to bytes or string. Ideally
54this would be the size of the http body, which is highly application dependent. As with other
55initial buffer lengths, further allocation will be performed until the necessary length is
56achieved. A smaller number will result in more vec resizing, and a larger number will result in
57unnecessary allocation.
58
59**Default**: `128`
60
61**Unit**: byte count
62
63
64### `copy_loops_per_yield`
65
66A sort of cooperative task yielding knob. Decreasing this number will improve tail latencies at a
67slight cost to total throughput for fast clients. This will have more of an impact on servers that
68spend a lot of time in IO compared to app handlers.
69
70**Default**: `16`
71
72**Unit**: the number of consecutive `Poll::Ready` async writes to perform before yielding
73the task back to the runtime.
74
75### `response_header_initial_capacity`
76
77The number of response headers to allocate space for on conn creation. Headers will grow on
78insertion when they reach this size.
79
80**Default**: `16`
81
82**Unit**: Header count
83
84### `received_body_max_preallocate`
85
86When we receive a fixed-length (not chunked-encoding) body that is smaller than this size, we can
87allocate a buffer with exactly the right size before we receive the body. However, if this is
88unbounded, malicious clients can issue headers with large content-length and then keep the
89connection open without sending any bytes, allowing them to allocate memory faster than their
90bandwidth usage. This does not limit the ability to receive fixed-length bodies larger than this,
91but the memory allocation will grow as with chunked bodies. Note that this has no impact on chunked
92bodies. If this is set higher than the `received_body_max_len`, this parameter has no effect. This
93parameter only impacts [`ReceivedBody::read_string`] and [`ReceivedBody::read_bytes`].
94
95**Default**: `1mb` in bytes
96
97**Unit**: Byte count
98
99
100## Security parameters
101
102These parameters represent worst cases, to delineate between malicious (or malformed) requests and
103acceptable ones.
104
105### `head_max_len`
106
107The maximum length allowed before the http body begins for a given request.
108
109**Default**: `8kb` in bytes
110
111**Unit**: Byte count
112
113### `received_body_max_len`
114
115The maximum length of a received body. This applies to both chunked and fixed-length request bodies,
116and the correct value will be application dependent.
117
118**Default**: `500mb` in bytes
119
120**Unit**: Byte count
121
122*/
123
124#[derive(Clone, Copy, Debug)]
125pub struct HttpConfig {
126    pub(crate) head_max_len: usize,
127    pub(crate) received_body_max_len: u64,
128    pub(crate) max_headers: usize,
129    pub(crate) response_buffer_len: usize,
130    pub(crate) request_buffer_initial_len: usize,
131    pub(crate) response_header_initial_capacity: usize,
132    pub(crate) copy_loops_per_yield: usize,
133    pub(crate) received_body_initial_len: usize,
134    pub(crate) received_body_max_preallocate: usize,
135}
136
137#[allow(missing_docs)]
138impl HttpConfig {
139    /// See [`response_buffer_len`][HttpConfig#response_buffer_len]
140    #[must_use]
141    pub fn with_response_buffer_len(mut self, response_buffer_len: usize) -> Self {
142        self.response_buffer_len = response_buffer_len;
143        self
144    }
145
146    /// See [`request_buffer_initial_len`][HttpConfig#request_buffer_initial_len]
147    #[must_use]
148    pub fn with_request_buffer_initial_len(mut self, request_buffer_initial_len: usize) -> Self {
149        self.request_buffer_initial_len = request_buffer_initial_len;
150        self
151    }
152
153    /// See [`head_max_len`][HttpConfig#head_max_len]
154    #[must_use]
155    pub fn with_head_max_len(mut self, head_max_len: usize) -> Self {
156        self.head_max_len = head_max_len;
157        self
158    }
159
160    /// See [`response_header_initial_capacity`][HttpConfig#resopnse_header_initial_capacity]
161    #[must_use]
162    pub fn with_response_header_initial_capacity(
163        mut self,
164        response_header_initial_capacity: usize,
165    ) -> Self {
166        self.response_header_initial_capacity = response_header_initial_capacity;
167        self
168    }
169
170    /// See [`copy_loops_per_yield`][HttpConfig#copy_loops_per_yield]
171    #[must_use]
172    pub fn with_copy_loops_per_yield(mut self, copy_loops_per_yield: usize) -> Self {
173        self.copy_loops_per_yield = copy_loops_per_yield;
174        self
175    }
176
177    /// See [`received_body_max_len`][HttpConfig#received_body_max_len]
178    #[must_use]
179    pub fn with_received_body_max_len(mut self, received_body_max_len: u64) -> Self {
180        self.received_body_max_len = received_body_max_len;
181        self
182    }
183
184    /// See [`received_body_max_len`][HttpConfig#received_body_max_len]
185    #[must_use]
186    pub fn with_received_body_max_preallocate(
187        mut self,
188        received_body_max_preallocate: usize,
189    ) -> Self {
190        self.received_body_max_preallocate = received_body_max_preallocate;
191        self
192    }
193}
194
195impl Default for HttpConfig {
196    fn default() -> Self {
197        DEFAULT_CONFIG
198    }
199}