From b64464562a02a642a3cf16ea072f39621da21980 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Thu, 28 May 2020 16:07:31 -0700 Subject: [PATCH] feat(http2): allow configuring the HTTP/2 frame size The default of 16K is taken from h2. --- src/client/conn.rs | 12 ++++++++++++ src/proto/h2/client.rs | 4 ++++ src/proto/h2/server.rs | 6 +++++- src/server/conn.rs | 12 ++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/client/conn.rs b/src/client/conn.rs index 42d75faa..71312704 100644 --- a/src/client/conn.rs +++ b/src/client/conn.rs @@ -525,6 +525,18 @@ impl Builder { self } + /// Sets the maximum frame size to use for HTTP2. + /// + /// Passing `None` will do nothing. + /// + /// If not set, hyper will use a default. + pub fn http2_max_frame_size(&mut self, sz: impl Into>) -> &mut Self { + if let Some(sz) = sz.into() { + self.h2_builder.max_frame_size = sz; + } + self + } + /// Sets an interval for HTTP2 Ping frames should be sent to keep a /// connection alive. /// diff --git a/src/proto/h2/client.rs b/src/proto/h2/client.rs index 6633b1bf..41b8e1b0 100644 --- a/src/proto/h2/client.rs +++ b/src/proto/h2/client.rs @@ -30,12 +30,14 @@ type ConnEof = oneshot::Receiver; // for performance. const DEFAULT_CONN_WINDOW: u32 = 1024 * 1024 * 5; // 5mb const DEFAULT_STREAM_WINDOW: u32 = 1024 * 1024 * 2; // 2mb +const DEFAULT_MAX_FRAME_SIZE: u32 = 1024 * 16; // 16kb #[derive(Clone, Debug)] pub(crate) struct Config { pub(crate) adaptive_window: bool, pub(crate) initial_conn_window_size: u32, pub(crate) initial_stream_window_size: u32, + pub(crate) max_frame_size: u32, #[cfg(feature = "runtime")] pub(crate) keep_alive_interval: Option, #[cfg(feature = "runtime")] @@ -50,6 +52,7 @@ impl Default for Config { adaptive_window: false, initial_conn_window_size: DEFAULT_CONN_WINDOW, initial_stream_window_size: DEFAULT_STREAM_WINDOW, + max_frame_size: DEFAULT_MAX_FRAME_SIZE, #[cfg(feature = "runtime")] keep_alive_interval: None, #[cfg(feature = "runtime")] @@ -74,6 +77,7 @@ where let (h2_tx, mut conn) = Builder::default() .initial_window_size(config.initial_stream_window_size) .initial_connection_window_size(config.initial_conn_window_size) + .max_frame_size(config.max_frame_size) .enable_push(false) .handshake::<_, SendBuf>(io) .await diff --git a/src/proto/h2/server.rs b/src/proto/h2/server.rs index 50572262..4762a920 100644 --- a/src/proto/h2/server.rs +++ b/src/proto/h2/server.rs @@ -26,12 +26,14 @@ use crate::{Body, Response}; // so is more likely to use more resources than a client would. const DEFAULT_CONN_WINDOW: u32 = 1024 * 1024; // 1mb const DEFAULT_STREAM_WINDOW: u32 = 1024 * 1024; // 1mb +const DEFAULT_MAX_FRAME_SIZE: u32 = 1024 * 16; // 16kb #[derive(Clone, Debug)] pub(crate) struct Config { pub(crate) adaptive_window: bool, pub(crate) initial_conn_window_size: u32, pub(crate) initial_stream_window_size: u32, + pub(crate) max_frame_size: u32, pub(crate) max_concurrent_streams: Option, #[cfg(feature = "runtime")] pub(crate) keep_alive_interval: Option, @@ -45,6 +47,7 @@ impl Default for Config { adaptive_window: false, initial_conn_window_size: DEFAULT_CONN_WINDOW, initial_stream_window_size: DEFAULT_STREAM_WINDOW, + max_frame_size: DEFAULT_MAX_FRAME_SIZE, max_concurrent_streams: None, #[cfg(feature = "runtime")] keep_alive_interval: None, @@ -98,7 +101,8 @@ where let mut builder = h2::server::Builder::default(); builder .initial_window_size(config.initial_stream_window_size) - .initial_connection_window_size(config.initial_conn_window_size); + .initial_connection_window_size(config.initial_conn_window_size) + .max_frame_size(config.max_frame_size); if let Some(max) = config.max_concurrent_streams { builder.max_concurrent_streams(max); } diff --git a/src/server/conn.rs b/src/server/conn.rs index fec1f975..76fac003 100644 --- a/src/server/conn.rs +++ b/src/server/conn.rs @@ -309,6 +309,18 @@ impl Http { self } + /// Sets the maximum frame size to use for HTTP2. + /// + /// Passing `None` will do nothing. + /// + /// If not set, hyper will use a default. + pub fn http2_max_frame_size(&mut self, sz: impl Into>) -> &mut Self { + if let Some(sz) = sz.into() { + self.h2_builder.max_frame_size = sz; + } + self + } + /// Sets the [`SETTINGS_MAX_CONCURRENT_STREAMS`][spec] option for HTTP2 /// connections. ///