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