github.com/projectcontour/contour@v1.28.2/site/content/docs/v1.16.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.