From 148e202fa3bf8ec2919635ace9e8733d4cbcf780 Mon Sep 17 00:00:00 2001 From: Brian Hardock Date: Wed, 5 Nov 2025 14:11:19 -0700 Subject: [PATCH] Allow configurable max buffer size for HTTP connections Signed-off-by: Brian Hardock --- crates/trigger-http/src/lib.rs | 11 +++++++++++ crates/trigger-http/src/server.rs | 12 +++++++++++- .../src/runtimes/in_process_spin.rs | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/crates/trigger-http/src/lib.rs b/crates/trigger-http/src/lib.rs index cc14d35f0c..2aaeb9582d 100644 --- a/crates/trigger-http/src/lib.rs +++ b/crates/trigger-http/src/lib.rs @@ -52,6 +52,10 @@ pub struct CliArgs { #[clap(long, env = "SPIN_TLS_KEY", requires = "tls-cert")] pub tls_key: Option, + /// Sets the maximum buffer size (in bytes) for the HTTP connection. The minimum value allowed is 8192. + #[clap(long, env = "SPIN_HTTP1_MAX_BUF_SIZE")] + pub http1_max_buf_size: Option, + #[clap(long = "find-free-port")] pub find_free_port: bool, } @@ -78,6 +82,7 @@ pub struct HttpTrigger { listen_addr: SocketAddr, tls_config: Option, find_free_port: bool, + http1_max_buf_size: Option, } impl Trigger for HttpTrigger { @@ -88,12 +93,14 @@ impl Trigger for HttpTrigger { fn new(cli_args: Self::CliArgs, app: &spin_app::App) -> anyhow::Result { let find_free_port = cli_args.find_free_port; + let http1_max_buf_size = cli_args.http1_max_buf_size; Self::new( app, cli_args.address, cli_args.into_tls_config(), find_free_port, + http1_max_buf_size, ) } @@ -117,6 +124,7 @@ impl HttpTrigger { listen_addr: SocketAddr, tls_config: Option, find_free_port: bool, + http1_max_buf_size: Option, ) -> anyhow::Result { Self::validate_app(app)?; @@ -124,6 +132,7 @@ impl HttpTrigger { listen_addr, tls_config, find_free_port, + http1_max_buf_size, }) } @@ -136,12 +145,14 @@ impl HttpTrigger { listen_addr, tls_config, find_free_port, + http1_max_buf_size, } = self; let server = Arc::new(HttpServer::new( listen_addr, tls_config, find_free_port, trigger_app, + http1_max_buf_size, )?); Ok(server) } diff --git a/crates/trigger-http/src/server.rs b/crates/trigger-http/src/server.rs index 917f4c4fb6..6aa53f6fa2 100644 --- a/crates/trigger-http/src/server.rs +++ b/crates/trigger-http/src/server.rs @@ -58,6 +58,8 @@ pub struct HttpServer { listen_addr: SocketAddr, /// The TLS configuration for the server. tls_config: Option, + /// The maximum buffer size for an HTTP1 connection. + http1_max_buf_size: Option, /// Whether to find a free port if the specified port is already in use. find_free_port: bool, /// Request router. @@ -77,6 +79,7 @@ impl HttpServer { tls_config: Option, find_free_port: bool, trigger_app: TriggerApp, + http1_max_buf_size: Option, ) -> anyhow::Result { // This needs to be a vec before building the router to handle duplicate routes let component_trigger_configs = trigger_app @@ -139,6 +142,7 @@ impl HttpServer { find_free_port, router, trigger_app, + http1_max_buf_size, component_trigger_configs, component_handler_types, }) @@ -491,7 +495,13 @@ impl HttpServer { client_addr: SocketAddr, ) { task::spawn(async move { - if let Err(err) = Builder::new(TokioExecutor::new()) + let mut server_builder = Builder::new(TokioExecutor::new()); + + if let Some(http1_max_buf_size) = self.http1_max_buf_size { + server_builder.http1().max_buf_size(http1_max_buf_size); + } + + if let Err(err) = server_builder .serve_connection( TokioIo::new(stream), service_fn(move |request| { diff --git a/tests/testing-framework/src/runtimes/in_process_spin.rs b/tests/testing-framework/src/runtimes/in_process_spin.rs index 5387ecbdf7..4656d272fa 100644 --- a/tests/testing-framework/src/runtimes/in_process_spin.rs +++ b/tests/testing-framework/src/runtimes/in_process_spin.rs @@ -104,7 +104,7 @@ async fn initialize_trigger( .await?; let app = spin_app::App::new("my-app", locked_app); - let trigger = HttpTrigger::new(&app, "127.0.0.1:80".parse().unwrap(), None, false)?; + let trigger = HttpTrigger::new(&app, "127.0.0.1:80".parse().unwrap(), None, false, None)?; let mut builder = TriggerAppBuilder::<_, FactorsBuilder>::new(trigger); let trigger_app = builder .build(