use core::time::Duration;
pub const DEFAULT_READ_BUF_LIMIT: usize = 1024 * 1024;
pub const DEFAULT_WRITE_BUF_LIMIT: usize = 8192 + 4096 * 100;
pub const DEFAULT_HEADER_LIMIT: usize = 64;
#[derive(Copy, Clone)]
pub struct HttpServiceConfig<
const HEADER_LIMIT: usize = DEFAULT_HEADER_LIMIT,
const READ_BUF_LIMIT: usize = DEFAULT_READ_BUF_LIMIT,
const WRITE_BUF_LIMIT: usize = DEFAULT_WRITE_BUF_LIMIT,
> {
pub(crate) vectored_write: bool,
pub(crate) keep_alive_timeout: Duration,
pub(crate) request_head_timeout: Duration,
pub(crate) tls_accept_timeout: Duration,
pub(crate) peek_protocol: bool,
pub(crate) h2_max_concurrent_streams: u32,
pub(crate) h2_initial_window_size: u32,
pub(crate) h2_max_frame_size: u32,
pub(crate) h2_max_header_list_size: u32,
}
impl Default for HttpServiceConfig {
fn default() -> Self {
Self::new()
}
}
impl HttpServiceConfig {
pub const fn new() -> Self {
Self {
vectored_write: true,
keep_alive_timeout: Duration::from_secs(5),
request_head_timeout: Duration::from_secs(5),
tls_accept_timeout: Duration::from_secs(3),
peek_protocol: false,
h2_max_concurrent_streams: 256,
h2_initial_window_size: 65_535,
h2_max_frame_size: 16_384,
h2_max_header_list_size: 16 * 1024 * 1024,
}
}
}
impl<const HEADER_LIMIT: usize, const READ_BUF_LIMIT: usize, const WRITE_BUF_LIMIT: usize>
HttpServiceConfig<HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT>
{
pub const fn disable_vectored_write(mut self) -> Self {
self.vectored_write = false;
self
}
pub const fn keep_alive_timeout(mut self, dur: Duration) -> Self {
self.keep_alive_timeout = dur;
self
}
pub const fn request_head_timeout(mut self, dur: Duration) -> Self {
self.request_head_timeout = dur;
self
}
pub const fn tls_accept_timeout(mut self, dur: Duration) -> Self {
self.tls_accept_timeout = dur;
self
}
pub const fn max_read_buf_size<const READ_BUF_LIMIT_2: usize>(
self,
) -> HttpServiceConfig<HEADER_LIMIT, READ_BUF_LIMIT_2, WRITE_BUF_LIMIT> {
assert!(READ_BUF_LIMIT_2 >= 32, "READ_BUF_LIMIT must be no less than 32 bytes");
h2_frame_read_buf_check(READ_BUF_LIMIT_2, self.h2_max_frame_size as _);
self.mutate_const_generic::<HEADER_LIMIT, READ_BUF_LIMIT_2, WRITE_BUF_LIMIT>()
}
pub const fn max_write_buf_size<const WRITE_BUF_LIMIT_2: usize>(
self,
) -> HttpServiceConfig<HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT_2> {
self.mutate_const_generic::<HEADER_LIMIT, READ_BUF_LIMIT, WRITE_BUF_LIMIT_2>()
}
pub const fn max_request_headers<const HEADER_LIMIT_2: usize>(
self,
) -> HttpServiceConfig<HEADER_LIMIT_2, READ_BUF_LIMIT, WRITE_BUF_LIMIT> {
self.mutate_const_generic::<HEADER_LIMIT_2, READ_BUF_LIMIT, WRITE_BUF_LIMIT>()
}
pub const fn h2_max_concurrent_streams(mut self, val: u32) -> Self {
self.h2_max_concurrent_streams = val;
self
}
pub const fn h2_initial_window_size(mut self, val: u32) -> Self {
self.h2_initial_window_size = val;
self
}
pub const fn h2_max_frame_size(mut self, val: u32) -> Self {
h2_frame_read_buf_check(READ_BUF_LIMIT, val as _);
self.h2_max_frame_size = val;
self
}
pub const fn h2_max_header_list_size(mut self, val: u32) -> Self {
self.h2_max_header_list_size = val;
self
}
pub const fn peek_protocol(mut self) -> Self {
self.peek_protocol = true;
self
}
#[doc(hidden)]
pub const fn mutate_const_generic<
const HEADER_LIMIT2: usize,
const READ_BUF_LIMIT2: usize,
const WRITE_BUF_LIMIT2: usize,
>(
self,
) -> HttpServiceConfig<HEADER_LIMIT2, READ_BUF_LIMIT2, WRITE_BUF_LIMIT2> {
HttpServiceConfig {
vectored_write: self.vectored_write,
keep_alive_timeout: self.keep_alive_timeout,
request_head_timeout: self.request_head_timeout,
tls_accept_timeout: self.tls_accept_timeout,
peek_protocol: self.peek_protocol,
h2_max_concurrent_streams: self.h2_max_concurrent_streams,
h2_initial_window_size: self.h2_initial_window_size,
h2_max_frame_size: self.h2_max_frame_size,
h2_max_header_list_size: self.h2_max_header_list_size,
}
}
}
const fn h2_frame_read_buf_check(read_buf_size: usize, h2_max_frame_size: usize) {
assert!(
read_buf_size >= (h2_max_frame_size + 9),
"max_read_buf_size must be at least h2_max_frame_size + 9 for HTTP2 to work"
);
}