From c3affb9acc1faeebacb1266033eb9a0124943ced Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 12:03:26 +0000 Subject: [PATCH 1/2] feat: Make server timeouts configurable This change introduces configurable server-side timeouts for the HTTP interceptor proxy. The following timeouts can now be set via environment variables: - KEDA_HTTP_SERVER_READ_TIMEOUT: Sets the ReadTimeout for the proxy server. - KEDA_HTTP_SERVER_WRITE_TIMEOUT: Sets the WriteTimeout for the proxy server. - KEDA_HTTP_SERVER_IDLE_TIMEOUT: Sets the IdleTimeout for the proxy server. These timeouts provide more granular control over the connection behavior between clients and the interceptor, allowing for longer timeout capabilities as you requested. The default for these timeouts is "0s", which means: - For ReadTimeout: No timeout. - For WriteTimeout: No timeout. - For IdleTimeout: Go's default http.Server behavior (uses TCP keep-alives). Validation has been added to ensure these timeout values cannot be negative. --- interceptor/config/timeouts.go | 6 ++++++ interceptor/config/validate.go | 11 +++++++++++ interceptor/main.go | 4 ++-- pkg/http/server.go | 18 ++++++++++++++---- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/interceptor/config/timeouts.go b/interceptor/config/timeouts.go index d79f71947..e6f612632 100644 --- a/interceptor/config/timeouts.go +++ b/interceptor/config/timeouts.go @@ -34,6 +34,12 @@ type Timeouts struct { // after sending request headers if the server returned an Expect: 100-continue // header ExpectContinueTimeout time.Duration `envconfig:"KEDA_HTTP_EXPECT_CONTINUE_TIMEOUT" default:"1s"` + // ServerReadTimeout is the maximum duration for reading the entire request, including the body. + ServerReadTimeout time.Duration `envconfig:"KEDA_HTTP_SERVER_READ_TIMEOUT" default:"0s"` + // ServerWriteTimeout is the maximum duration before timing out writes of the response. + ServerWriteTimeout time.Duration `envconfig:"KEDA_HTTP_SERVER_WRITE_TIMEOUT" default:"0s"` + // ServerIdleTimeout is the maximum amount of time to wait for the next request when keep-alives are enabled. + ServerIdleTimeout time.Duration `envconfig:"KEDA_HTTP_SERVER_IDLE_TIMEOUT" default:"0s"` } // Backoff returns a wait.Backoff based on the timeouts in t diff --git a/interceptor/config/validate.go b/interceptor/config/validate.go index 738059b92..c706b9537 100644 --- a/interceptor/config/validate.go +++ b/interceptor/config/validate.go @@ -34,5 +34,16 @@ func Validate(srvCfg *Serving, timeoutsCfg Timeouts, lggr logr.Logger) error { endpointsCachePollInterval, ) } + + if timeoutsCfg.ServerReadTimeout < 0 { + return fmt.Errorf("timeout value KEDA_HTTP_SERVER_READ_TIMEOUT must not be negative") + } + if timeoutsCfg.ServerWriteTimeout < 0 { + return fmt.Errorf("timeout value KEDA_HTTP_SERVER_WRITE_TIMEOUT must not be negative") + } + if timeoutsCfg.ServerIdleTimeout < 0 { + return fmt.Errorf("timeout value KEDA_HTTP_SERVER_IDLE_TIMEOUT must not be negative") + } + return nil } diff --git a/interceptor/main.go b/interceptor/main.go index c01970c40..7b43d0970 100644 --- a/interceptor/main.go +++ b/interceptor/main.go @@ -470,7 +470,7 @@ func runProxyServer( addr := fmt.Sprintf("0.0.0.0:%d", port) logger.Info("proxy server starting", "address", addr) if tlsEnabled { - return kedahttp.ServeContext(ctx, addr, rootHandler, tlsCfg) + return kedahttp.ServeContext(ctx, addr, rootHandler, tlsCfg, timeouts) } - return kedahttp.ServeContext(ctx, addr, rootHandler, nil) + return kedahttp.ServeContext(ctx, addr, rootHandler, nil, timeouts) } diff --git a/pkg/http/server.go b/pkg/http/server.go index f037a5d12..e952b591d 100644 --- a/pkg/http/server.go +++ b/pkg/http/server.go @@ -5,14 +5,24 @@ import ( "crypto/tls" "net/http" + "github.com/kedacore/http-add-on/interceptor/config" "github.com/kedacore/http-add-on/pkg/util" ) -func ServeContext(ctx context.Context, addr string, hdl http.Handler, tlsConfig *tls.Config) error { +func ServeContext( + ctx context.Context, + addr string, + hdl http.Handler, + tlsConfig *tls.Config, + timeouts *config.Timeouts, +) error { srv := &http.Server{ - Handler: hdl, - Addr: addr, - TLSConfig: tlsConfig, + Handler: hdl, + Addr: addr, + TLSConfig: tlsConfig, + ReadTimeout: timeouts.ServerReadTimeout, + WriteTimeout: timeouts.ServerWriteTimeout, + IdleTimeout: timeouts.ServerIdleTimeout, } go func() { From 2e1114ecf9b6522d564bf9ff7224cc1f57154e20 Mon Sep 17 00:00:00 2001 From: bazooka720 Date: Tue, 17 Jun 2025 08:15:51 -0400 Subject: [PATCH 2/2] Update timeouts.go Signed-off-by: bazooka720 --- interceptor/config/timeouts.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interceptor/config/timeouts.go b/interceptor/config/timeouts.go index e6f612632..7c393a079 100644 --- a/interceptor/config/timeouts.go +++ b/interceptor/config/timeouts.go @@ -35,11 +35,11 @@ type Timeouts struct { // header ExpectContinueTimeout time.Duration `envconfig:"KEDA_HTTP_EXPECT_CONTINUE_TIMEOUT" default:"1s"` // ServerReadTimeout is the maximum duration for reading the entire request, including the body. - ServerReadTimeout time.Duration `envconfig:"KEDA_HTTP_SERVER_READ_TIMEOUT" default:"0s"` + ServerReadTimeout time.Duration `envconfig:"KEDA_HTTP_SERVER_READ_TIMEOUT" default:"120s"` // ServerWriteTimeout is the maximum duration before timing out writes of the response. - ServerWriteTimeout time.Duration `envconfig:"KEDA_HTTP_SERVER_WRITE_TIMEOUT" default:"0s"` + ServerWriteTimeout time.Duration `envconfig:"KEDA_HTTP_SERVER_WRITE_TIMEOUT" default:"120s"` // ServerIdleTimeout is the maximum amount of time to wait for the next request when keep-alives are enabled. - ServerIdleTimeout time.Duration `envconfig:"KEDA_HTTP_SERVER_IDLE_TIMEOUT" default:"0s"` + ServerIdleTimeout time.Duration `envconfig:"KEDA_HTTP_SERVER_IDLE_TIMEOUT" default:"120s"` } // Backoff returns a wait.Backoff based on the timeouts in t