sui_http/
config.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::time::Duration;
5
6const DEFAULT_HTTP2_KEEPALIVE_TIMEOUT_SECS: u64 = 20;
7
8#[derive(Debug, Clone)]
9pub struct Config {
10    init_stream_window_size: Option<u32>,
11    init_connection_window_size: Option<u32>,
12    max_concurrent_streams: Option<u32>,
13    pub(crate) tcp_keepalive: Option<Duration>,
14    pub(crate) tcp_nodelay: bool,
15    http2_keepalive_interval: Option<Duration>,
16    http2_keepalive_timeout: Option<Duration>,
17    http2_adaptive_window: Option<bool>,
18    http2_max_pending_accept_reset_streams: Option<usize>,
19    http2_max_header_list_size: Option<u32>,
20    max_frame_size: Option<u32>,
21    pub(crate) accept_http1: bool,
22    enable_connect_protocol: bool,
23    pub(crate) max_connection_age: Option<Duration>,
24    pub(crate) allow_insecure: bool,
25}
26
27impl Default for Config {
28    fn default() -> Self {
29        Self {
30            init_stream_window_size: None,
31            init_connection_window_size: None,
32            max_concurrent_streams: None,
33            tcp_keepalive: None,
34            tcp_nodelay: true,
35            http2_keepalive_interval: None,
36            http2_keepalive_timeout: None,
37            http2_adaptive_window: None,
38            http2_max_pending_accept_reset_streams: None,
39            http2_max_header_list_size: None,
40            max_frame_size: None,
41            accept_http1: true,
42            enable_connect_protocol: true,
43            max_connection_age: None,
44            allow_insecure: false,
45        }
46    }
47}
48
49impl Config {
50    /// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2
51    /// stream-level flow control.
52    ///
53    /// Default is 65,535
54    ///
55    /// [spec]: https://httpwg.org/specs/rfc9113.html#InitialWindowSize
56    pub fn initial_stream_window_size(self, sz: impl Into<Option<u32>>) -> Self {
57        Self {
58            init_stream_window_size: sz.into(),
59            ..self
60        }
61    }
62
63    /// Sets the max connection-level flow control for HTTP2
64    ///
65    /// Default is 65,535
66    pub fn initial_connection_window_size(self, sz: impl Into<Option<u32>>) -> Self {
67        Self {
68            init_connection_window_size: sz.into(),
69            ..self
70        }
71    }
72
73    /// Sets the [`SETTINGS_MAX_CONCURRENT_STREAMS`][spec] option for HTTP2
74    /// connections.
75    ///
76    /// Default is no limit (`None`).
77    ///
78    /// [spec]: https://httpwg.org/specs/rfc9113.html#n-stream-concurrency
79    pub fn max_concurrent_streams(self, max: impl Into<Option<u32>>) -> Self {
80        Self {
81            max_concurrent_streams: max.into(),
82            ..self
83        }
84    }
85
86    /// Sets the maximum time option in milliseconds that a connection may exist
87    ///
88    /// Default is no limit (`None`).
89    pub fn max_connection_age(self, max_connection_age: Duration) -> Self {
90        Self {
91            max_connection_age: Some(max_connection_age),
92            ..self
93        }
94    }
95
96    /// Set whether HTTP2 Ping frames are enabled on accepted connections.
97    ///
98    /// If `None` is specified, HTTP2 keepalive is disabled, otherwise the duration
99    /// specified will be the time interval between HTTP2 Ping frames.
100    /// The timeout for receiving an acknowledgement of the keepalive ping
101    /// can be set with [`Config::http2_keepalive_timeout`].
102    ///
103    /// Default is no HTTP2 keepalive (`None`)
104    pub fn http2_keepalive_interval(self, http2_keepalive_interval: Option<Duration>) -> Self {
105        Self {
106            http2_keepalive_interval,
107            ..self
108        }
109    }
110
111    /// Sets a timeout for receiving an acknowledgement of the keepalive ping.
112    ///
113    /// If the ping is not acknowledged within the timeout, the connection will be closed.
114    /// Does nothing if http2_keep_alive_interval is disabled.
115    ///
116    /// Default is 20 seconds.
117    pub fn http2_keepalive_timeout(self, http2_keepalive_timeout: Option<Duration>) -> Self {
118        Self {
119            http2_keepalive_timeout,
120            ..self
121        }
122    }
123
124    /// Sets whether to use an adaptive flow control. Defaults to false.
125    /// Enabling this will override the limits set in http2_initial_stream_window_size and
126    /// http2_initial_connection_window_size.
127    pub fn http2_adaptive_window(self, enabled: Option<bool>) -> Self {
128        Self {
129            http2_adaptive_window: enabled,
130            ..self
131        }
132    }
133
134    /// Configures the maximum number of pending reset streams allowed before a GOAWAY will be sent.
135    ///
136    /// This will default to whatever the default in h2 is. As of v0.3.17, it is 20.
137    ///
138    /// See <https://github.com/hyperium/hyper/issues/2877> for more information.
139    pub fn http2_max_pending_accept_reset_streams(self, max: Option<usize>) -> Self {
140        Self {
141            http2_max_pending_accept_reset_streams: max,
142            ..self
143        }
144    }
145
146    /// Set whether TCP keepalive messages are enabled on accepted connections.
147    ///
148    /// If `None` is specified, keepalive is disabled, otherwise the duration
149    /// specified will be the time to remain idle before sending TCP keepalive
150    /// probes.
151    ///
152    /// Default is no keepalive (`None`)
153    pub fn tcp_keepalive(self, tcp_keepalive: Option<Duration>) -> Self {
154        Self {
155            tcp_keepalive,
156            ..self
157        }
158    }
159
160    /// Set the value of `TCP_NODELAY` option for accepted connections. Enabled by default.
161    pub fn tcp_nodelay(self, enabled: bool) -> Self {
162        Self {
163            tcp_nodelay: enabled,
164            ..self
165        }
166    }
167
168    /// Sets the max size of received header frames.
169    ///
170    /// This will default to whatever the default in hyper is. As of v1.4.1, it is 16 KiB.
171    pub fn http2_max_header_list_size(self, max: impl Into<Option<u32>>) -> Self {
172        Self {
173            http2_max_header_list_size: max.into(),
174            ..self
175        }
176    }
177
178    /// Sets the maximum frame size to use for HTTP2.
179    ///
180    /// Passing `None` will do nothing.
181    ///
182    /// If not set, will default from underlying transport.
183    pub fn max_frame_size(self, frame_size: impl Into<Option<u32>>) -> Self {
184        Self {
185            max_frame_size: frame_size.into(),
186            ..self
187        }
188    }
189
190    /// Allow this accepting http1 requests.
191    ///
192    /// Default is `true`.
193    pub fn accept_http1(self, accept_http1: bool) -> Self {
194        Config {
195            accept_http1,
196            ..self
197        }
198    }
199
200    /// Allow accepting insecure connections when a tls_config is provided.
201    ///
202    /// This will allow clients to connect both using TLS as well as without TLS on the same
203    /// network interface.
204    ///
205    /// Default is `false`.
206    ///
207    /// NOTE: This presently will only work for `tokio::net::TcpStream` IO connections
208    pub fn allow_insecure(self, allow_insecure: bool) -> Self {
209        Config {
210            allow_insecure,
211            ..self
212        }
213    }
214
215    pub(crate) fn connection_builder(
216        &self,
217    ) -> hyper_util::server::conn::auto::Builder<hyper_util::rt::TokioExecutor> {
218        let mut builder =
219            hyper_util::server::conn::auto::Builder::new(hyper_util::rt::TokioExecutor::new());
220
221        if !self.accept_http1 {
222            builder = builder.http2_only();
223        }
224
225        if self.enable_connect_protocol {
226            builder.http2().enable_connect_protocol();
227        }
228
229        let http2_keepalive_timeout = self
230            .http2_keepalive_timeout
231            .unwrap_or_else(|| Duration::new(DEFAULT_HTTP2_KEEPALIVE_TIMEOUT_SECS, 0));
232
233        builder
234            .http2()
235            .timer(hyper_util::rt::TokioTimer::new())
236            .initial_connection_window_size(self.init_connection_window_size)
237            .initial_stream_window_size(self.init_stream_window_size)
238            .max_concurrent_streams(self.max_concurrent_streams)
239            .keep_alive_interval(self.http2_keepalive_interval)
240            .keep_alive_timeout(http2_keepalive_timeout)
241            .adaptive_window(self.http2_adaptive_window.unwrap_or_default())
242            .max_pending_accept_reset_streams(self.http2_max_pending_accept_reset_streams)
243            .max_frame_size(self.max_frame_size);
244
245        if let Some(max_header_list_size) = self.http2_max_header_list_size {
246            builder.http2().max_header_list_size(max_header_list_size);
247        }
248
249        builder
250    }
251}