diff --git a/api/v1alpha1/timeout_types.go b/api/v1alpha1/timeout_types.go
index 36c0c320ed2..008582578d1 100644
--- a/api/v1alpha1/timeout_types.go
+++ b/api/v1alpha1/timeout_types.go
@@ -40,6 +40,11 @@ type HTTPTimeout struct {
//
// +optional
MaxConnectionDuration *gwapiv1.Duration `json:"maxConnectionDuration,omitempty"`
+
+ // RequestTimeout is the time until which entire response is received from the upstream.
+ //
+ // +optional
+ RequestTimeout *gwapiv1.Duration `json:"requestTimeout,omitempty" yaml:"requestTimeout,omitempty"`
}
type ClientTimeout struct {
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index cde4e3b90d7..1fad0493923 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -2629,6 +2629,11 @@ func (in *HTTPTimeout) DeepCopyInto(out *HTTPTimeout) {
*out = new(apisv1.Duration)
**out = **in
}
+ if in.RequestTimeout != nil {
+ in, out := &in.RequestTimeout, &out.RequestTimeout
+ *out = new(apisv1.Duration)
+ **out = **in
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPTimeout.
diff --git a/internal/gatewayapi/clustersettings.go b/internal/gatewayapi/clustersettings.go
index a05ad60ff26..4df7e19174d 100644
--- a/internal/gatewayapi/clustersettings.go
+++ b/internal/gatewayapi/clustersettings.go
@@ -81,11 +81,11 @@ func translateTrafficFeatures(policy *egv1a1.ClusterSettings) (*ir.TrafficFeatur
return ret, nil
}
-func buildClusterSettingsTimeout(policy egv1a1.ClusterSettings, traffic *ir.TrafficFeatures) (*ir.Timeout, error) {
+func buildClusterSettingsTimeout(policy egv1a1.ClusterSettings, routeTrafficFeatures *ir.TrafficFeatures) (*ir.Timeout, error) {
if policy.Timeout == nil {
- if traffic != nil {
+ if routeTrafficFeatures != nil {
// Don't lose any existing timeout definitions.
- return mergeTimeoutSettings(nil, traffic.Timeout), nil
+ return mergeTimeoutSettings(nil, routeTrafficFeatures.Timeout), nil
}
return nil, nil
}
@@ -109,6 +109,7 @@ func buildClusterSettingsTimeout(policy egv1a1.ClusterSettings, traffic *ir.Traf
if pto.HTTP != nil {
var cit *metav1.Duration
var mcd *metav1.Duration
+ var rt *metav1.Duration
if pto.HTTP.ConnectionIdleTimeout != nil {
d, err := time.ParseDuration(string(*pto.HTTP.ConnectionIdleTimeout))
@@ -128,19 +129,27 @@ func buildClusterSettingsTimeout(policy egv1a1.ClusterSettings, traffic *ir.Traf
}
}
+ if pto.HTTP.RequestTimeout != nil {
+ d, err := time.ParseDuration(string(*pto.HTTP.RequestTimeout))
+ if err != nil {
+ errs = errors.Join(errs, fmt.Errorf("invalid RequestTimeout value %s", *pto.HTTP.RequestTimeout))
+ } else {
+ rt = ptr.To(metav1.Duration{Duration: d})
+ }
+ }
+
to.HTTP = &ir.HTTPTimeout{
ConnectionIdleTimeout: cit,
MaxConnectionDuration: mcd,
+ RequestTimeout: rt,
}
}
- // http request timeout is translated during the gateway-api route resource translation
- // merge route timeout setting with backendtrafficpolicy timeout settings.
- // Merging is done after the clustersettings definitions are translated so that
- // clustersettings will override previous settings.
- if traffic != nil {
- to = mergeTimeoutSettings(to, traffic.Timeout)
+ // The timeout from route's TrafficFeatures takes precedence over the timeout in BTP
+ if routeTrafficFeatures != nil {
+ to = mergeTimeoutSettings(routeTrafficFeatures.Timeout, to)
}
+
return to, errs
}
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.in.yaml
index ef8843f70c4..30a9a3133ab 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.in.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.in.yaml
@@ -62,6 +62,8 @@ httpRoutes:
backendRefs:
- name: service-1
port: 8080
+ timeouts:
+ request: 1s
backendTrafficPolicies:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
@@ -79,6 +81,7 @@ backendTrafficPolicies:
http:
connectionIdleTimeout: 16s
maxConnectionDuration: 17s
+ requestTimeout: 18s
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
@@ -95,3 +98,4 @@ backendTrafficPolicies:
http:
connectionIdleTimeout: 21s
maxConnectionDuration: 22s
+ requestTimeout: 23s
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml
index 5213fc9d6a2..67cd04db0cd 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml
@@ -14,6 +14,7 @@ backendTrafficPolicies:
http:
connectionIdleTimeout: 21s
maxConnectionDuration: 22s
+ requestTimeout: 23s
tcp:
connectTimeout: 20s
status:
@@ -46,6 +47,7 @@ backendTrafficPolicies:
http:
connectionIdleTimeout: 16s
maxConnectionDuration: 17s
+ requestTimeout: 18s
tcp:
connectTimeout: 15s
status:
@@ -195,6 +197,8 @@ httpRoutes:
- backendRefs:
- name: service-1
port: 8080
+ timeouts:
+ request: 1s
matches:
- path:
value: /
@@ -289,6 +293,7 @@ xdsIR:
http:
connectionIdleTimeout: 16s
maxConnectionDuration: 17s
+ requestTimeout: 18s
tcp:
connectTimeout: 15s
envoy-gateway/gateway-2:
@@ -336,5 +341,6 @@ xdsIR:
http:
connectionIdleTimeout: 21s
maxConnectionDuration: 22s
+ requestTimeout: 1s # Overwritten by the request timeout in HTTPRoute
tcp:
connectTimeout: 20s
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 802efac5828..777884fe1cf 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -1911,6 +1911,7 @@ _Appears in:_
| --- | --- | --- | --- |
| `connectionIdleTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | The idle timeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection.
Default: 1 hour. |
| `maxConnectionDuration` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | The maximum duration of an HTTP connection.
Default: unlimited. |
+| `requestTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | RequestTimeout is the time until which entire response is received from the upstream. |
#### HTTPWasmCodeSource
diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md
index 802efac5828..777884fe1cf 100644
--- a/site/content/zh/latest/api/extension_types.md
+++ b/site/content/zh/latest/api/extension_types.md
@@ -1911,6 +1911,7 @@ _Appears in:_
| --- | --- | --- | --- |
| `connectionIdleTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | The idle timeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection.
Default: 1 hour. |
| `maxConnectionDuration` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | The maximum duration of an HTTP connection.
Default: unlimited. |
+| `requestTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | RequestTimeout is the time until which entire response is received from the upstream. |
#### HTTPWasmCodeSource