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}