diff --git a/config.toml b/config.toml index 6fe8961..f0ac4a2 100644 --- a/config.toml +++ b/config.toml @@ -1,6 +1,10 @@ port = ":8080" # Port to listen on for HTTP routes timeout = "1m" # How long to wait for a machine to wake / a route to become ready +request_header_timeout = "30s" # How long to wait for request headers response_header_timeout = "1m" # How long to wait for a response header, e.g. during slow or long-running requests/uploads +server_read_timeout = "10m" # How long to wait for the full request body from the client +server_write_timeout = "10m" # How long to wait for the full response to the client +server_idle_timeout = "120s" # How long to wait for the next request when keep-alive is enabled poll_interval = "5s" # How often to check health while waiting health_check_interval = "30s" # Background health check frequency health_cache_duration = "10s" # How long to trust a cached health result diff --git a/main.go b/main.go index ecae038..0bc73a8 100644 --- a/main.go +++ b/main.go @@ -106,7 +106,11 @@ func (r *realTicker) Stop() { r.t.Stop() } type Config struct { Port string `toml:"port"` Timeout string `toml:"timeout"` + RequestHeaderTimeout string `toml:"request_header_timeout,omitempty"` ResponseHeaderTimeout string `toml:"response_header_timeout,omitempty"` + ServerReadTimeout string `toml:"server_read_timeout,omitempty"` + ServerWriteTimeout string `toml:"server_write_timeout,omitempty"` + ServerIdleTimeout string `toml:"server_idle_timeout,omitempty"` PollInterval string `toml:"poll_interval"` HealthCheckInterval string `toml:"health_check_interval"` HealthCacheDuration string `toml:"health_cache_duration"` @@ -210,7 +214,11 @@ type routing struct { type ProxyConfig struct { Port string Timeout time.Duration + RequestHeaderTimeout time.Duration ResponseHeaderTimeout time.Duration + ServerReadTimeout time.Duration + ServerWriteTimeout time.Duration + ServerIdleTimeout time.Duration PollInterval time.Duration HealthCheckInterval time.Duration HealthCacheDuration time.Duration @@ -790,10 +798,10 @@ func (p *ProxyService) Start(ctx context.Context) error { server := &http.Server{ Addr: p.config.Port, Handler: mux, - ReadTimeout: 10 * time.Minute, - WriteTimeout: 10 * time.Minute, - IdleTimeout: 120 * time.Second, // 2 minutes for keep-alive connections - ReadHeaderTimeout: 30 * time.Second, + ReadTimeout: p.config.ServerReadTimeout, + WriteTimeout: p.config.ServerWriteTimeout, + IdleTimeout: p.config.ServerIdleTimeout, + ReadHeaderTimeout: p.config.RequestHeaderTimeout, MaxHeaderBytes: 1 << 20, } @@ -1348,6 +1356,14 @@ func LoadConfig(filename string, clock Clock) (*ProxyConfig, error) { return nil, fmt.Errorf("invalid timeout: %w", err) } + if config.RequestHeaderTimeout == "" { + config.RequestHeaderTimeout = "30s" + } + requestHeaderTimeout, err := time.ParseDuration(config.RequestHeaderTimeout) + if err != nil { + return nil, fmt.Errorf("invalid request_header_timeout: %w", err) + } + if config.ResponseHeaderTimeout == "" { config.ResponseHeaderTimeout = "1m" } @@ -1356,6 +1372,30 @@ func LoadConfig(filename string, clock Clock) (*ProxyConfig, error) { return nil, fmt.Errorf("invalid response_header_timeout: %w", err) } + if config.ServerReadTimeout == "" { + config.ServerReadTimeout = "10m" + } + serverReadTimeout, err := time.ParseDuration(config.ServerReadTimeout) + if err != nil { + return nil, fmt.Errorf("invalid server_read_timeout: %w", err) + } + + if config.ServerWriteTimeout == "" { + config.ServerWriteTimeout = "10m" + } + serverWriteTimeout, err := time.ParseDuration(config.ServerWriteTimeout) + if err != nil { + return nil, fmt.Errorf("invalid server_write_timeout: %w", err) + } + + if config.ServerIdleTimeout == "" { + config.ServerIdleTimeout = "120s" + } + serverIdleTimeout, err := time.ParseDuration(config.ServerIdleTimeout) + if err != nil { + return nil, fmt.Errorf("invalid server_idle_timeout: %w", err) + } + pollInterval, err := time.ParseDuration(config.PollInterval) if err != nil { return nil, fmt.Errorf("invalid poll_interval: %w", err) @@ -1391,7 +1431,11 @@ func LoadConfig(filename string, clock Clock) (*ProxyConfig, error) { SSLCertificate: config.SSLCertificate, SSLCertificateKey: config.SSLCertificateKey, Timeout: timeout, + RequestHeaderTimeout: requestHeaderTimeout, ResponseHeaderTimeout: responseHeaderTimeout, + ServerReadTimeout: serverReadTimeout, + ServerWriteTimeout: serverWriteTimeout, + ServerIdleTimeout: serverIdleTimeout, PollInterval: pollInterval, HealthCheckInterval: healthCheckInterval, HealthCacheDuration: healthCacheDuration,