Skip to content

Commit 606dcb1

Browse files
committed
add GEP-1323: Response Header Filter
Signed-off-by: Sanskar Jaiswal <[email protected]>
1 parent aceec27 commit 606dcb1

File tree

1 file changed

+209
-0
lines changed

1 file changed

+209
-0
lines changed

site-src/geps/gep-1323.md

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
# GEP 1323: Response Header Filter
2+
* Issue: [#1323](https://github.com/kubernetes-sigs/gateway-api/issues/1323)
3+
* Status: Implementable
4+
5+
## TLDR
6+
Similar to how we have `RequestHeaderModifier` in `HTTPRouteFilter`, which lets users modify request headers before the request is forwarded to a backend (or a group of backends), it’d be helpful to have a `ResponseHeaderModifier` field which would let users modify response headers before they are returned to the client.
7+
8+
## Goals
9+
* Provide a way to modify HTTP response headers in a `HTTPRoute`.
10+
* Provide a way to enforce modification of HTTP response headers at various levels using Policy Attachment.
11+
* Reuse existing types as much as possible to reduce boilerplate code.
12+
13+
## Non Goals
14+
* Provide a way to modify other parts of a HTTP response like status code.
15+
* Add fields specifically for standard headers such as `Cookie`.
16+
17+
## Introduction
18+
Currently, the `HTTPRouteFilter` API provides a way for request headers to be modified through the `RequestHeaderModifier` field of type `HTTPRequestHeaderModifier`. But, a similar API to modify response headers does not exist. This proposal intends to introduce a new field in `HTTPRouteFilter` named `ResponseHeaderModifier`.
19+
20+
## API
21+
We could introduce a new API named `HTTPResponseHeaderModifier` which would look exactly like the existing `HTTPRequestHeaderModifier` API. But since HTTP headers have the same semantics for both requests and responses, it makes more sense to rename `HTTPRequestHeaderModifier` to `HTTPHeaderModifier` and use this for both `RequestHeaderModifier` and `ResponseHeaderModifier`.
22+
23+
```golang
24+
// HTTPHeaderModifier defines a filter that modifies the headers of a HTTP
25+
// request or response.
26+
type HTTPHeaderModifier struct {
27+
// Set overwrites the request with the given header (name, value)
28+
// before the action.
29+
// +optional
30+
// +listType=map
31+
// +listMapKey=name
32+
// +kubebuilder:validation:MaxItems=16
33+
Set []HTTPHeader `json:"set,omitempty"`
34+
35+
// Add adds the given header(s) (name, value) to the request
36+
// before the action. It appends to any existing values associated
37+
// with the header name.
38+
39+
// +optional
40+
// +listType=map
41+
// +listMapKey=name
42+
// +kubebuilder:validation:MaxItems=16
43+
Add []HTTPHeader `json:"add,omitempty"`
44+
45+
// Remove the given header(s) from the HTTP request before the action. The
46+
// value of Remove is a list of HTTP header names. Note that the header
47+
// names are case-insensitive (see
48+
// https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
49+
// +optional
50+
// +kubebuilder:validation:MaxItems=16
51+
Remove []string `json:"remove,omitempty"`
52+
}
53+
```
54+
55+
Given the fact that this functionality is offered by only a few projects that currently implement Gateway API when using their own traffic routing CRDs, it’s better to support `ResponseHeaderModifier` as an _Extended_ feature, unlike `RequestHeaderModifier` which is a _Core_ feature. This will also not increase the difficulty of implementing Gateway API for any future ingress or service mesh.
56+
57+
This feature can be further extended via [Policy Attachment](../references/policy-attachment.md). The mechanism and use cases of this may be explored in a future GEP.
58+
59+
## Usage
60+
Adding support for this unlocks a lot of real world use cases. Let’s review a couple of them:
61+
62+
* A team has a frontend web app, along with two different versions of their backends exposed as Kubernetes services. If, the frontend needs to know which backend it’s talking to, this can be easily achieved without any modifications to the application code.
63+
64+
```yaml
65+
apiVersion: gateway.networking.k8s.io/v1beta1
66+
kind: HTTPRoute
67+
metadata:
68+
name: http-response-header
69+
spec:
70+
hostnames:
71+
- response.header.example
72+
rules:
73+
- backendRefs:
74+
- name: example-svc-beta
75+
weight: 50
76+
port: 80
77+
# set a custom header for all responses being sent from the beta build of the backend server.
78+
filters:
79+
- type: ResponseHeaderModifier
80+
responseHeaderModifier:
81+
add:
82+
name: build
83+
value: beta
84+
- name: example-svc-stable
85+
weight: 50
86+
port: 80
87+
```
88+
89+
* Cookies can be automatically injected into the response of services. This can enable services to identify users that were redirected to a certain backend.
90+
91+
```yaml
92+
apiVersion: gateway.networking.k8s.io/v1beta1
93+
kind: HTTPRoute
94+
metadata:
95+
name: http-response-header
96+
spec:
97+
hostnames:
98+
- response.header.example
99+
rules:
100+
# match against any requests that has the cookie set due to the below rule
101+
- matches:
102+
- headers:
103+
type: Exact
104+
name: Cookie
105+
value: user=insider
106+
backendRefs:
107+
- name: foo-svc
108+
port: 8080
109+
110+
- filters:
111+
- type: ResponseHeaderModifier
112+
# set cookies for all requests being forwarded to this service
113+
responseHeaderModifier:
114+
set:
115+
name: Set-Cookie
116+
value: user=insider
117+
backendRefs:
118+
- name: example-svc
119+
weight: 1
120+
port: 80
121+
```
122+
123+
> Note: Some projects like Envoy support interpolating a few predefined [variables into header values](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#custom-request-response-headers). Similar functionality might be supported by other implementations but its unlikely to be portable and thus has been excluded from the API for the time being.
124+
125+
## Prior Art
126+
A few projects that implement Gateway API already have support for similar functionality (in their custom CRDs), like:
127+
* Istio’s `VirtualService`:
128+
129+
```yaml
130+
apiVersion: networking.istio.io/v1alpha3
131+
kind: VirtualService
132+
metadata:
133+
name: reviews-route
134+
spec:
135+
hosts:
136+
- reviews.prod.svc.cluster.local
137+
http:
138+
- headers:
139+
request:
140+
set:
141+
test: "true"
142+
route:
143+
- destination:
144+
host: reviews.prod.svc.cluster.local
145+
subset: v2
146+
weight: 25
147+
- destination:
148+
host: reviews.prod.svc.cluster.local
149+
subset: v1
150+
headers:
151+
response:
152+
remove:
153+
- foo
154+
weight: 75
155+
```
156+
157+
* Contour’s `HTTPProxy`:
158+
159+
```yaml
160+
apiVersion: projectcontour.io/v1
161+
kind: HTTPProxy
162+
metadata:
163+
name: basic
164+
spec:
165+
virtualhost:
166+
fqdn: foo-basic.bar.com
167+
routes:
168+
- conditions:
169+
- prefix: /
170+
services:
171+
- name: s1
172+
port: 80
173+
responseHeadersPolicy:
174+
set:
175+
name: test
176+
value: true
177+
```
178+
179+
* Ingress NGINX:
180+
181+
```yaml
182+
apiVersion: networking.k8s.io/v1
183+
kind: Ingress
184+
metadata:
185+
name: nginx-headers
186+
annotations:
187+
nginx.ingress.kubernetes.io/configuration-snippet: |
188+
add_header ingress nginx;
189+
spec:
190+
ingressClassName: nginx
191+
rules:
192+
- host: custom.configuration.com
193+
http:
194+
paths:
195+
- path: /
196+
pathType: Prefix
197+
backend:
198+
service:
199+
name: http-svc
200+
port:
201+
number: 80
202+
```
203+
204+
## External Links
205+
* [Contour `HeaderValue`](https://projectcontour.io/docs/v1.22.0/config/api/#projectcontour.io/v1.HeaderValue)
206+
* [Istio `Headers`](https://istio.io/latest/docs/reference/config/networking/virtual-service/#Headers)
207+
* [Ingress NGINX Configuration Snippets](https://kubernetes.github.io/ingress-nginx/examples/customization/configuration-snippets/)
208+
* [NGINX `add_header` directive](https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header)
209+

0 commit comments

Comments
 (0)