github.com/projectcontour/contour@v1.28.2/site/content/docs/v1.13.1/config/request-rewriting.md (about) 1 # Request Rewriting 2 3 ## Path Rewriting 4 5 HTTPProxy supports rewriting the HTTP request URL path prior to delivering the request to the backend service. 6 Rewriting is performed after a routing decision has been made, and never changes the request destination. 7 8 The `pathRewritePolicy` field specifies how the path prefix should be rewritten. 9 The `replacePrefix` rewrite policy specifies a replacement string for a HTTP request path prefix match. 10 When this field is present, the path prefix that the request matched is replaced by the text specified in the `replacement` field. 11 If the HTTP request path is longer than the matched prefix, the remainder of the path is unchanged. 12 13 ```yaml 14 apiVersion: projectcontour.io/v1 15 kind: HTTPProxy 16 metadata: 17 name: rewrite-example 18 namespace: default 19 spec: 20 virtualhost: 21 fqdn: rewrite.bar.com 22 routes: 23 - services: 24 - name: s1 25 port: 80 26 pathRewritePolicy: 27 replacePrefix: 28 - replacement: /new/prefix 29 ``` 30 31 The `replacePrefix` field accepts an array of possible replacements. 32 When more than one `replacePrefix` array element is present, the `prefix` field can be used to disambiguate which replacement to apply. 33 34 If no `prefix` field is present, the replacement is applied to all prefix matches made against the route. 35 If a `prefix` field is present, the replacement is applied only to routes that have an exactly matching prefix condition. 36 Specifying more than one `replacePrefix` entry is mainly useful when a HTTPProxy document is included into multiple parent documents. 37 38 ```yaml 39 apiVersion: projectcontour.io/v1 40 kind: HTTPProxy 41 metadata: 42 name: rewrite-example 43 namespace: default 44 spec: 45 virtualhost: 46 fqdn: rewrite.bar.com 47 routes: 48 - services: 49 - name: s1 50 port: 80 51 conditions: 52 - prefix: /v1/api 53 pathRewritePolicy: 54 replacePrefix: 55 - prefix: /v1/api 56 replacement: /app/api/v1 57 - prefix: / 58 replacement: /app 59 ``` 60 61 ## Header Rewriting 62 63 HTTPProxy supports rewriting HTTP request and response headers. 64 The `Set` operation sets a HTTP header value, creating it if it doesn't already exist or overwriting it if it does. 65 The `Remove` operation removes a HTTP header. 66 The `requestHeadersPolicy` field is used to rewrite headers on a HTTP request, and the `responseHeadersPolicy` is used to rewrite headers on a HTTP response. 67 These fields can be specified on a route or on a specific service, depending on the rewrite granularity you need. 68 69 ```yaml 70 apiVersion: projectcontour.io/v1 71 kind: HTTPProxy 72 metadata: 73 name: header-rewrite-example 74 spec: 75 virtualhost: 76 fqdn: header.bar.com 77 routes: 78 - services: 79 - name: s1 80 port: 80 81 requestHeadersPolicy: 82 set: 83 - name: Host 84 value: external.dev 85 remove: 86 - Some-Header 87 - Some-Other-Header 88 ``` 89 90 Manipulating headers is also supported per-Service or per-Route. Headers can be set or 91 removed from the request or response as follows: 92 93 per-Service: 94 95 ```yaml 96 apiVersion: projectcontour.io/v1 97 kind: HTTPProxy 98 metadata: 99 name: header-manipulation 100 namespace: default 101 spec: 102 virtualhost: 103 fqdn: headers.bar.com 104 routes: 105 - services: 106 - name: s1 107 port: 80 108 requestHeadersPolicy: 109 set: 110 - name: X-Foo 111 value: bar 112 remove: 113 - X-Baz 114 responseHeadersPolicy: 115 set: 116 - name: X-Service-Name 117 value: s1 118 remove: 119 - X-Internal-Secret 120 ``` 121 122 per-Route: 123 124 ```yaml 125 apiVersion: projectcontour.io/v1 126 kind: HTTPProxy 127 metadata: 128 name: header-manipulation 129 namespace: default 130 spec: 131 virtualhost: 132 fqdn: headers.bar.com 133 routes: 134 - services: 135 - name: s1 136 port: 80 137 requestHeadersPolicy: 138 set: 139 - name: X-Foo 140 value: bar 141 remove: 142 - X-Baz 143 responseHeadersPolicy: 144 set: 145 - name: X-Service-Name 146 value: s1 147 remove: 148 - X-Internal-Secret 149 ``` 150 151 In these examples we are setting the header `X-Foo` with value `baz` on requests 152 and stripping `X-Baz`. We are then setting `X-Service-Name` on the response with 153 value `s1`, and removing `X-Internal-Secret`. 154 155 ### Dynamic Header Values 156 157 It is sometimes useful to set a header value using a dynamic value such as the 158 hostname where the Envoy Pod is running (`%HOSTNAME%`) or the subject of the 159 TLS client certificate (`%DOWNSTREAM_PEER_SUBJECT%`) or based on another header 160 (`%REQ(header)%`). 161 162 Examples: 163 ``` 164 requestHeadersPolicy: 165 set: 166 - name: X-Envoy-Hostname 167 value: "%HOSTNAME%" 168 - name: X-Host-Protocol 169 value: "%REQ(Host)% - %PROTOCOL%" 170 responseHeadersPolicy: 171 set: 172 - name: X-Envoy-Response-Flags 173 value: "%RESPONSE_FLAGS%" 174 ``` 175 176 Contour supports most of the custom request/response header variables offered 177 by Envoy - see the <a 178 href="https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#custom-request-response-headers">Envoy 179 documentation </a> for details of what each of these resolve to: 180 181 * `%DOWNSTREAM_REMOTE_ADDRESS%` 182 * `%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%` 183 * `%DOWNSTREAM_LOCAL_ADDRESS%` 184 * `%DOWNSTREAM_LOCAL_ADDRESS_WITHOUT_PORT%` 185 * `%DOWNSTREAM_LOCAL_PORT%` 186 * `%DOWNSTREAM_LOCAL_URI_SAN%` 187 * `%DOWNSTREAM_PEER_URI_SAN%` 188 * `%DOWNSTREAM_LOCAL_SUBJECT%` 189 * `%DOWNSTREAM_PEER_SUBJECT%` 190 * `%DOWNSTREAM_PEER_ISSUER%` 191 * `%DOWNSTREAM_TLS_SESSION_ID%` 192 * `%DOWNSTREAM_TLS_CIPHER%` 193 * `%DOWNSTREAM_TLS_VERSION%` 194 * `%DOWNSTREAM_PEER_FINGERPRINT_256%` 195 * `%DOWNSTREAM_PEER_FINGERPRINT_1%` 196 * `%DOWNSTREAM_PEER_SERIAL%` 197 * `%DOWNSTREAM_PEER_CERT%` 198 * `%DOWNSTREAM_PEER_CERT_V_START%` 199 * `%DOWNSTREAM_PEER_CERT_V_END%` 200 * `%HOSTNAME%` 201 * `%REQ(header-name)%` 202 * `%PROTOCOL%` 203 * `%RESPONSE_FLAGS%` 204 * `%RESPONSE_CODE_DETAILS%` 205 * `%UPSTREAM_REMOTE_ADDRESS%` 206 207 Note that Envoy passes variables that can't be expanded through unchanged or 208 skips them entirely - for example: 209 * `%UPSTREAM_REMOTE_ADDRESS%` as a request header remains as 210 `%UPSTREAM_REMOTE_ADDRESS%` because as noted in the Envoy docs: "The upstream 211 remote address cannot be added to request headers as the upstream host has not 212 been selected when custom request headers are generated." 213 * `%DOWNSTREAM_TLS_VERSION%` is skipped if TLS is not in use 214 * Envoy ignores REQ headers that refer to an non-existent header - for example 215 `%REQ(Host)%` works as expected but `%REQ(Missing-Header)%` is skipped 216 217 Contour already sets the `X-Request-Start` request header to 218 `t=%START_TIME(%s.%3f)%` which is the Unix epoch time when the request 219 started. 220 221 To enable setting header values based on the destination service Contour also supports: 222 223 * `%CONTOUR_NAMESPACE%` 224 * `%CONTOUR_SERVICE_NAME%` 225 * `%CONTOUR_SERVICE_PORT%` 226 227 For example, with the following HTTPProxy object that has a per-Service requestHeadersPolicy using these variables: 228 ``` 229 # httpproxy.yaml 230 apiVersion: projectcontour.io/v1 231 kind: HTTPProxy 232 metadata: 233 name: basic 234 namespace: myns 235 spec: 236 virtualhost: 237 fqdn: foo-basic.bar.com 238 routes: 239 - conditions: 240 - prefix: / 241 services: 242 - name: s1 243 port: 80 244 requestHeadersPolicy: 245 set: 246 - name: l5d-dst-override 247 value: "%CONTOUR_SERVICE_NAME%.%CONTOUR_NAMESPACE%.svc.cluster.local:%CONTOUR_SERVICE_PORT%" 248 ``` 249 the values would be: 250 * `CONTOUR_NAMESPACE: "myns"` 251 * `CONTOUR_SERVICE_NAME: "s1"` 252 * `CONTOUR_SERVICE_PORT: "80"` 253 254 and the `l5-dst-override` header would be set to `s1.myns.svc.cluster.local:80`. 255 256 For per-Route requestHeadersPolicy only `%CONTOUR_NAMESPACE%` is set and using 257 `%CONTOUR_SERVICE_NAME%` and `%CONTOUR_SERVICE_PORT%` will end up as the 258 literal values `%%CONTOUR_SERVICE_NAME%%` and `%%CONTOUR_SERVICE_PORT%%`, 259 respectively.