diff --git a/.schema/config.schema.json b/.schema/config.schema.json index 63fca93c44..e5715510e8 100644 --- a/.schema/config.schema.json +++ b/.schema/config.schema.json @@ -4,6 +4,50 @@ "title": "ORY Oathkeeper Configuration", "type": "object", "definitions": { + "serverTimeout": { + "title": "HTTP Timeouts", + "description": "Control the HTTP timeouts.", + "type": "object", + "additionalProperties": false, + "properties": { + "read": { + "title": "HTTP Read Timeout", + "type": "string", + "default": "5s", + "pattern": "^[0-9]+(ns|us|ms|s|m|h)$", + "description": "The maximum duration for reading the entire request, including the body.", + "examples": [ + "5s", + "5m", + "5h" + ] + }, + "write": { + "title": "HTTP Write Timeout", + "type": "string", + "default": "120s", + "pattern": "^[0-9]+(ns|us|ms|s|m|h)$", + "description": "The maximum duration before timing out writes of the response. Increase this parameter to prevent unexpected closing a client connection if an upstream request is responding slowly.", + "examples": [ + "5s", + "5m", + "5h" + ] + }, + "idle": { + "title": "HTTP Idle Timeout", + "type": "string", + "default": "120s", + "pattern": "^[0-9]+(ns|us|ms|s|m|h)$", + "description": " The maximum amount of time to wait for any action of a request session, reading data or writing the response.", + "examples": [ + "5s", + "5m", + "5h" + ] + } + } + }, "retry": { "type": "object", "additionalProperties": false, @@ -985,6 +1029,9 @@ "title": "Host", "description": "The network interface to listen on." }, + "timeout": { + "$ref": "#/definitions/serverTimeout" + }, "cors": { "$ref": "#/definitions/cors" }, @@ -1015,48 +1062,7 @@ "description": "The network interface to listen on. Leave empty to listen on all interfaces." }, "timeout": { - "title": "HTTP Timeouts", - "description": "Control the reverse proxy's HTTP timeouts.", - "type": "object", - "additionalProperties": false, - "properties": { - "read": { - "title": "HTTP Read Timeout", - "type": "string", - "default": "5s", - "pattern": "^[0-9]+(ns|us|ms|s|m|h)$", - "description": "The maximum duration for reading the entire request, including the body.", - "examples": [ - "5s", - "5m", - "5h" - ] - }, - "write": { - "title": "HTTP Write Timeout", - "type": "string", - "default": "120s", - "pattern": "^[0-9]+(ns|us|ms|s|m|h)$", - "description": "The maximum duration before timing out writes of the response. Increase this parameter to prevent unexpected closing a client connection if an upstream request is responding slowly.", - "examples": [ - "5s", - "5m", - "5h" - ] - }, - "idle": { - "title": "HTTP Idle Timeout", - "type": "string", - "default": "120s", - "pattern": "^[0-9]+(ns|us|ms|s|m|h)$", - "description": " The maximum amount of time to wait for any action of a request session, reading data or writing the response.", - "examples": [ - "5s", - "5m", - "5h" - ] - } - } + "$ref": "#/definitions/serverTimeout" }, "cors": { "$ref": "#/definitions/cors" diff --git a/cmd/server/server.go b/cmd/server/server.go index 7557150996..57ef8e9612 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -92,9 +92,12 @@ func runAPI(d driver.Driver, n *negroni.Negroni, logger *logrus.Logger, prom *me certs := cert("api", logger) addr := d.Configuration().APIServeAddress() server := graceful.WithDefaults(&http.Server{ - Addr: addr, - Handler: h, - TLSConfig: &tls.Config{Certificates: certs}, + Addr: addr, + Handler: h, + TLSConfig: &tls.Config{Certificates: certs}, + ReadTimeout: d.Configuration().APIReadTimeout(), + WriteTimeout: d.Configuration().APIWriteTimeout(), + IdleTimeout: d.Configuration().APIIdleTimeout(), }) if err := graceful.Graceful(func() error { diff --git a/driver/configuration/provider.go b/driver/configuration/provider.go index 6ce9bd7826..3a111a203a 100644 --- a/driver/configuration/provider.go +++ b/driver/configuration/provider.go @@ -43,6 +43,10 @@ type Provider interface { ProxyWriteTimeout() time.Duration ProxyIdleTimeout() time.Duration + APIReadTimeout() time.Duration + APIWriteTimeout() time.Duration + APIIdleTimeout() time.Duration + AccessRuleRepositories() []url.URL AccessRuleMatchingStrategy() MatchingStrategy diff --git a/driver/configuration/provider_viper.go b/driver/configuration/provider_viper.go index b85bf60991..b87ed060c5 100644 --- a/driver/configuration/provider_viper.go +++ b/driver/configuration/provider_viper.go @@ -45,6 +45,9 @@ const ( ViperKeyProxyServeAddressPort = "serve.proxy.port" ViperKeyAPIServeAddressHost = "serve.api.host" ViperKeyAPIServeAddressPort = "serve.api.port" + ViperKeyAPIReadTimeout = "serve.api.timeout.read" + ViperKeyAPIWriteTimeout = "serve.api.timeout.write" + ViperKeyAPIIdleTimeout = "serve.api.timeout.idle" ViperKeyPrometheusServeAddressHost = "serve.prometheus.host" ViperKeyPrometheusServeAddressPort = "serve.prometheus.port" ViperKeyPrometheusServeMetricsPath = "serve.prometheus.metrics_path" @@ -173,6 +176,18 @@ func (v *ViperProvider) ProxyServeAddress() string { ) } +func (v *ViperProvider) APIReadTimeout() time.Duration { + return viperx.GetDuration(v.l, ViperKeyAPIReadTimeout, time.Second*5) +} + +func (v *ViperProvider) APIWriteTimeout() time.Duration { + return viperx.GetDuration(v.l, ViperKeyAPIWriteTimeout, time.Second*10) +} + +func (v *ViperProvider) APIIdleTimeout() time.Duration { + return viperx.GetDuration(v.l, ViperKeyAPIIdleTimeout, time.Second*120) +} + func (v *ViperProvider) APIServeAddress() string { return fmt.Sprintf( "%s:%d", diff --git a/internal/config/.oathkeeper.yaml b/internal/config/.oathkeeper.yaml index 40d77feee9..7f5cea7293 100644 --- a/internal/config/.oathkeeper.yaml +++ b/internal/config/.oathkeeper.yaml @@ -47,6 +47,12 @@ serve: api: port: 1235 host: 127.0.0.2 + + timeout: + read: 1s + write: 2s + idle: 3s + cors: enabled: true allowed_origins: