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