From e387445102af2f7135332ace72d89f1b6a04ea57 Mon Sep 17 00:00:00 2001 From: discord9 <55937128+discord9@users.noreply.github.com> Date: Fri, 9 Oct 2026 15:47:11 +0800 Subject: [PATCH] fix: honor HTTP timeout headers with no default deadline Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> --- src/servers/src/http.rs | 47 +++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/servers/src/http.rs b/src/servers/src/http.rs index 7f2688d30cf..4e012f7d1dc 100644 --- a/src/servers/src/http.rs +++ b/src/servers/src/http.rs @@ -1032,17 +1032,12 @@ impl HttpServer { /// Attaches middlewares and debug routes to the router. /// Callers should call this method after [HttpServer::make_app()]. pub fn build(&self, router: Router) -> Result { - let timeout_layer = if self.options.timeout != Duration::default() { - Some( - ServiceBuilder::new().layer( - DynamicTimeoutLayer::new(self.options.timeout) - .with_status_code_fn(Self::request_timeout_status_code), - ), - ) - } else { - info!("HTTP server timeout is disabled"); - None - }; + let timeout_layer = Some( + ServiceBuilder::new().layer( + DynamicTimeoutLayer::new(self.options.timeout) + .with_status_code_fn(Self::request_timeout_status_code), + ), + ); let body_limit_layer = if self.options.body_limit != ReadableSize(0) { Some( ServiceBuilder::new() @@ -2116,6 +2111,36 @@ mod test { assert_ne!(response.status(), StatusCode::NOT_FOUND); } + #[tokio::test] + async fn test_http_header_timeout_with_disabled_default() { + let (tx, _rx) = mpsc::channel(100); + let options = HttpOptions { + timeout: Duration::ZERO, + ..Default::default() + }; + let app = make_test_app_custom(tx, options); + let client = TestClient::new(app).await; + assert!( + tokio::time::timeout( + Duration::from_millis(10), + client.get("/test/timeout").send() + ) + .await + .is_err(), + "no header with a disabled global timeout should remain unlimited" + ); + let response = tokio::time::timeout( + Duration::from_secs(1), + client + .get("/test/timeout") + .header(GREPTIME_DB_HEADER_TIMEOUT, "10ms") + .send(), + ) + .await + .expect("request with header timeout should complete"); + assert_eq!(response.status(), StatusCode::REQUEST_TIMEOUT); + } + #[tokio::test] async fn test_http_server_request_timeout() { common_telemetry::init_default_ut_logging();