github.com/projectcontour/contour@v1.28.2/site/content/docs/1.25/config/request-routing.md (about)

     1  # Request Routing
     2  
     3  A HTTPProxy object must have at least one route or include defined.
     4  In this example, any requests to `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*` will be routed to the Service `s2` using the prefix conditions. Requests to `multi-path.bar.com/feed` will be routed to Service `s2` using exact match condition.
     5  All other requests to the host `multi-path.bar.com` will be routed to the Service `s1`.
     6  
     7  ```yaml
     8  # httpproxy-multiple-paths.yaml
     9  apiVersion: projectcontour.io/v1
    10  kind: HTTPProxy
    11  metadata:
    12    name: multiple-paths
    13    namespace: default
    14  spec:
    15    virtualhost:
    16      fqdn: multi-path.bar.com
    17    routes:
    18      - conditions:
    19        - prefix: / # matches everything else
    20        services:
    21          - name: s1
    22            port: 80
    23      - conditions:
    24        - prefix: /blog # matches `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*`
    25        services:
    26          - name: s2
    27            port: 80
    28      - conditions:
    29        - exact: /feed # matches `multi-path.bar.com/feed` only
    30        services:
    31          - name: s2
    32            port: 80
    33  ```
    34  
    35  In the following example, we match on headers and query parameters and send to different services, with a default route if those do not match.
    36  
    37  ```yaml
    38  # httpproxy-multiple-headers.yaml
    39  apiVersion: projectcontour.io/v1
    40  kind: HTTPProxy
    41  metadata:
    42    name: multiple-paths
    43    namespace: default
    44  spec:
    45    virtualhost:
    46      fqdn: multi-path.bar.com
    47    routes:
    48      - conditions:
    49        - header:
    50            name: x-os
    51            contains: ios
    52        services:
    53          - name: s1
    54            port: 80
    55      - conditions:
    56        - header:
    57            name: x-os
    58            contains: android
    59        services:
    60          - name: s2
    61            port: 80
    62      - conditions:
    63        - queryParameter:
    64            name: os
    65            exact: other
    66            ignoreCase: true
    67        services:
    68          - name: s3
    69            port: 80
    70      - services:
    71          - name: s4
    72            port: 80
    73  ```
    74  
    75  ## Conditions
    76  
    77  Each Route entry in a HTTPProxy **may** contain one or more conditions.
    78  These conditions are combined with an AND operator on the route passed to Envoy.
    79  Conditions can be either a `prefix`, `exact`, `header` or a `queryParameter` condition. `prefix` and `exact`
    80  conditions cannot be used together in one condition block.
    81  
    82  #### Prefix conditions
    83  
    84  Paths defined are matched using prefix conditions.
    85  Up to one prefix condition may be present in any condition block.
    86  
    87  Prefix conditions **must** start with a `/` if they are present.
    88  
    89  #### Exact conditions
    90  
    91  Paths defined are matched using exact conditions.
    92  Up to one exact condition may be present in any condition block. Any condition block can
    93  either have an exact condition or prefix condition, but not both together. Exact conditions are
    94  only allowed in route match conditions and not in include match conditions.
    95  
    96  Exact conditions **must** start with a `/` if they are present.
    97  
    98  #### Header conditions
    99  
   100  For `header` conditions there is one required field, `name`, and six operator fields: `present`, `notpresent`, `contains`, `notcontains`, `exact`, and `notexact`.
   101  
   102  - `present` is a boolean and checks that the header is present. The value will not be checked.
   103  
   104  - `notpresent` similarly checks that the header is *not* present.
   105  
   106  - `contains` is a string, and checks that the header contains the string. `notcontains` similarly checks that the header does *not* contain the string.
   107  
   108  - `exact` is a string, and checks that the header exactly matches the whole string. `notexact` checks that the header does *not* exactly match the whole string.
   109  
   110  #### Query parameter conditions
   111  
   112  Similar to the `header` conditions, `queryParameter` conditions also require the
   113  `name` field to be specified, which represents the name of the query parameter
   114  e.g. `search` when the query string looks like `/?search=term` and `term`
   115  representing the value.
   116  
   117  There are six operator fields: `exact`, `prefix`, `suffix`, `regex`, `contains`
   118  and `present` and a modifier `ignoreCase` which can be used together with all of
   119  the operator fields except `regex` and `present`.
   120  
   121  - `exact` is a string, and checks that the query parameter value exactly matches
   122    the whole string.
   123  
   124  - `prefix` is a string, and checks that the query parameter value is prefixed by
   125    the given value.
   126  
   127  - `suffix` is a string, and checks that the query parameter value is suffixed by
   128    the given value.
   129  
   130  - `regex` is a string representing a regular expression, and checks that the
   131    query parameter value matches against the given regular expression.
   132  
   133  - `contains` is a string, and checks that the query parameter value contains
   134    the given string.
   135  
   136  - `present` is a boolean, and checks that the query parameter is present. The
   137    value will not be checked.
   138  
   139  - `ignoreCase` is a boolean, and if set to `true` it will enable case
   140    insensitive matching for any of the string operator matching methods.
   141  
   142  ## Request Redirection
   143  
   144  HTTP redirects can be implemented in HTTPProxy using `requestRedirectPolicy` on a route.
   145  In the following basic example, requests to `example.com` are redirected to `www.example.com`.
   146  We configure a root HTTPProxy for `example.com` that contains redirect configuration.
   147  We also configure a root HTTPProxy for `www.example.com` that represents the destination of the redirect.
   148  
   149  ```yaml
   150  apiVersion: projectcontour.io/v1
   151  kind: HTTPProxy
   152  metadata:
   153    name: example-com
   154  spec:
   155    virtualhost:
   156      fqdn: example.com
   157    routes:
   158      - conditions:
   159        - prefix: /
   160        requestRedirectPolicy:
   161          hostname: www.example.com
   162  ```
   163  
   164  ```yaml
   165  apiVersion: projectcontour.io/v1
   166  kind: HTTPProxy
   167  metadata:
   168    name: www-example-com
   169  spec:
   170    virtualhost:
   171      fqdn: www.example.com
   172    routes:
   173      - conditions:
   174        - prefix: /
   175        services:
   176          - name: s1
   177            port: 80
   178  ```
   179  
   180  In addition to specifying the hostname to set in the `location` header, the scheme, port, and returned status code of the redirect response can be configured.
   181  Configuration of the path or a path prefix replacement to modify the path of the returned `location` can be included as well.
   182  See [the API specification][3] for more detail.
   183  
   184  ## Multiple Upstreams
   185  
   186  One of the key HTTPProxy features is the ability to support multiple services for a given path:
   187  
   188  ```yaml
   189  # httpproxy-multiple-upstreams.yaml
   190  apiVersion: projectcontour.io/v1
   191  kind: HTTPProxy
   192  metadata:
   193    name: multiple-upstreams
   194    namespace: default
   195  spec:
   196    virtualhost:
   197      fqdn: multi.bar.com
   198    routes:
   199      - services:
   200          - name: s1
   201            port: 80
   202          - name: s2
   203            port: 80
   204  ```
   205  
   206  In this example, requests for `multi.bar.com/` will be load balanced across two Kubernetes Services, `s1`, and `s2`.
   207  This is helpful when you need to split traffic for a given URL across two different versions of an application.
   208  
   209  ### Upstream Weighting
   210  
   211  Building on multiple upstreams is the ability to define relative weights for upstream Services.
   212  This is commonly used for canary testing of new versions of an application when you want to send a small fraction of traffic to a specific Service.
   213  
   214  ```yaml
   215  # httpproxy-weight-shifting.yaml
   216  apiVersion: projectcontour.io/v1
   217  kind: HTTPProxy
   218  metadata:
   219    name: weight-shifting
   220    namespace: default
   221  spec:
   222    virtualhost:
   223      fqdn: weights.bar.com
   224    routes:
   225      - services:
   226          - name: s1
   227            port: 80
   228            weight: 10
   229          - name: s2
   230            port: 80
   231            weight: 90
   232  ```
   233  
   234  In this example, we are sending 10% of the traffic to Service `s1`, while Service `s2` receives the remaining 90% of traffic.
   235  
   236  HTTPProxy weighting follows some specific rules:
   237  
   238  - If no weights are specified for a given route, it's assumed even distribution across the Services.
   239  - Weights are relative and do not need to add up to 100. If all weights for a route are specified, then the "total" weight is the sum of those specified. As an example, if weights are 20, 30, 20 for three upstreams, the total weight would be 70. In this example, a weight of 30 would receive approximately 42.9% of traffic (30/70 = .4285).
   240  - If some weights are specified but others are not, then it's assumed that upstreams without weights have an implicit weight of zero, and thus will not receive traffic.
   241  
   242  ### Traffic mirroring
   243  
   244  Per route,  a service can be nominated as a mirror.
   245  The mirror service will receive a copy of the read traffic sent to any non mirror service.
   246  The mirror traffic is considered _read only_, any response by the mirror will be discarded.
   247  
   248  This service can be useful for recording traffic for later replay or for smoke testing new deployments.
   249  
   250  ```yaml
   251  apiVersion: projectcontour.io/v1
   252  kind: HTTPProxy
   253  metadata:
   254    name: traffic-mirror
   255    namespace: default
   256  spec:
   257    virtualhost:
   258      fqdn: www.example.com
   259    routes:
   260      - conditions:
   261        - prefix: /
   262        services:
   263          - name: www
   264            port: 80
   265          - name: www-mirror
   266            port: 80
   267            mirror: true
   268  ```
   269  
   270  ## Response Timeouts
   271  
   272  Each Route can be configured to have a timeout policy and a retry policy as shown:
   273  
   274  ```yaml
   275  # httpproxy-response-timeout.yaml
   276  apiVersion: projectcontour.io/v1
   277  kind: HTTPProxy
   278  metadata:
   279    name: response-timeout
   280    namespace: default
   281  spec:
   282    virtualhost:
   283      fqdn: timeout.bar.com
   284    routes:
   285    - timeoutPolicy:
   286        response: 1s
   287        idle: 10s
   288        idleConnection: 60s
   289      retryPolicy:
   290        count: 3
   291        perTryTimeout: 150ms
   292      services:
   293      - name: s1
   294        port: 80
   295  ```
   296  
   297  In this example, requests to `timeout.bar.com/` will have a response timeout policy of 1s.
   298  This refers to the time that spans between the point at which complete client request has been processed by the proxy, and when the response from the server has been completely processed.
   299  
   300  - `timeoutPolicy.response` Timeout for receiving a response from the server after processing a request from client.
   301  If not supplied, Envoy's default value of 15s applies.
   302  More information can be found in [Envoy's documentation][4].
   303  - `timeoutPolicy.idle` Timeout for how long the proxy should wait while there is no activity during single request/response (for HTTP/1.1) or stream (for HTTP/2).
   304  Timeout will not trigger while HTTP/1.1 connection is idle between two consecutive requests.
   305  If not specified, there is no per-route idle timeout, though a connection manager-wide stream idle timeout default of 5m still applies.
   306  More information can be found in [Envoy's documentation][6].
   307  - `timeoutPolicy.idleConnection` Timeout for how long connection from the proxy to the upstream service is kept when there are no active requests.
   308  If not supplied, Envoy’s default value of 1h applies.
   309  More information can be found in [Envoy's documentation][8].
   310  
   311  TimeoutPolicy durations are expressed in the Go [Duration format][5].
   312  Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
   313  The string "infinity" is also a valid input and specifies no timeout.
   314  A value of "0s" will be treated as if the field were not set, i.e. by using Envoy's default behavior.
   315  Example input values: "300ms", "5s", "1m".
   316  
   317  - `retryPolicy`: A retry will be attempted if the server returns an error code in the 5xx range, or if the server takes more than `retryPolicy.perTryTimeout` to process a request.
   318  
   319  - `retryPolicy.count` specifies the maximum number of retries allowed. This parameter is optional and defaults to 1. Set to -1 to disable. If set to 0, the Envoy default of 1 is used.
   320  
   321  - `retryPolicy.perTryTimeout` specifies the timeout per retry. If this field is greater than the request timeout, it is ignored. This parameter is optional.
   322    If left unspecified, `timeoutPolicy.request` will be used.
   323  
   324  ## Load Balancing Strategy
   325  
   326  Each route can have a load balancing strategy applied to determine which of its Endpoints is selected for the request.
   327  The following list are the options available to choose from:
   328  
   329  - `RoundRobin`: Each healthy upstream Endpoint is selected in round-robin order (Default strategy if none selected).
   330  - `WeightedLeastRequest`:  The least request load balancer uses different algorithms depending on whether hosts have the same or different weights in an attempt to route traffic based upon the number of active requests or the load at the time of selection. 
   331  - `Random`: The random strategy selects a random healthy Endpoints.
   332  - `RequestHash`: The request hashing strategy allows for load balancing based on request attributes. An upstream Endpoint is selected based on the hash of an element of a request. For example, requests that contain a consistent value in an HTTP request header will be routed to the same upstream Endpoint. Currently, only hashing of HTTP request headers, query parameters and the source IP of a request is supported.
   333  - `Cookie`: The cookie load balancing strategy is similar to the request hash strategy and is a convenience feature to implement session affinity, as described below.
   334  
   335  More information on the load balancing strategy can be found in [Envoy's documentation][7].
   336  
   337  The following example defines the strategy for the route `/` as `WeightedLeastRequest`.
   338  
   339  ```yaml
   340  # httpproxy-lb-strategy.yaml
   341  apiVersion: projectcontour.io/v1
   342  kind: HTTPProxy
   343  metadata:
   344    name: lb-strategy
   345    namespace: default
   346  spec:
   347    virtualhost:
   348      fqdn: strategy.bar.com
   349    routes:
   350      - conditions:
   351        - prefix: /
   352        services:
   353          - name: s1-strategy
   354            port: 80
   355          - name: s2-strategy
   356            port: 80
   357        loadBalancerPolicy:
   358          strategy: WeightedLeastRequest
   359  ```
   360  
   361  The below example demonstrates how request hash load balancing policies can be configured:
   362  
   363  Request hash headers
   364  ```yaml
   365  # httpproxy-lb-request-hash.yaml
   366  apiVersion: projectcontour.io/v1
   367  kind: HTTPProxy
   368  metadata:
   369    name: lb-request-hash
   370    namespace: default
   371  spec:
   372    virtualhost:
   373      fqdn: request-hash.bar.com
   374    routes:
   375    - conditions:
   376      - prefix: /
   377      services:
   378      - name: httpbin
   379        port: 8080
   380      loadBalancerPolicy:
   381        strategy: RequestHash
   382        requestHashPolicies:
   383        - headerHashOptions:
   384            headerName: X-Some-Header
   385          terminal: true
   386        - headerHashOptions:
   387            headerName: User-Agent
   388        - hashSourceIP: true
   389  ```
   390  In this example, if a client request contains the `X-Some-Header` header, the value of the header will be hashed and used to route to an upstream Endpoint. This could be used to implement a similar workflow to cookie-based session affinity by passing a consistent value for this header. If it is present, because it is set as a `terminal` hash option, Envoy will not continue on to process to `User-Agent` header or source IP to calculate a hash. If `X-Some-Header` is not present, Envoy will use the `User-Agent` header value to make a routing decision along with the source IP of the client making the request. These policies can be used alone or as shown for an advanced routing decision.
   391  
   392  
   393  Request hash source ip
   394  ```yaml
   395  # httpproxy-lb-request-hash-ip.yaml
   396  apiVersion: projectcontour.io/v1
   397  kind: HTTPProxy
   398  metadata:
   399    name: lb-request-hash 
   400    namespace: default
   401  spec:
   402    virtualhost:
   403      fqdn: request-hash.bar.com
   404    routes:
   405    - conditions:
   406      - prefix: /
   407      services:
   408      - name: httpbin
   409        port: 8080
   410      loadBalancerPolicy:
   411        strategy: RequestHash
   412        requestHashPolicies:
   413        - hashSourceIP: true
   414  ```
   415  
   416  Request hash query parameters
   417  ```yaml
   418  # httpproxy-lb-request-hash.yaml
   419  apiVersion: projectcontour.io/v1
   420  kind: HTTPProxy
   421  metadata:
   422    name: lb-request-hash 
   423    namespace: default
   424  spec:
   425    virtualhost:
   426      fqdn: request-hash.bar.com
   427    routes:
   428    - conditions:
   429      - prefix: /
   430      services:
   431      - name: httpbin
   432        port: 8080
   433      loadBalancerPolicy:
   434        strategy: RequestHash
   435        requestHashPolicies:
   436        - queryParameterHashOptions:
   437            prameterName: param1
   438          terminal: true
   439        - queryParameterHashOptions:
   440            parameterName: param2
   441  ```
   442  
   443  ## Session Affinity
   444  
   445  Session affinity, also known as _sticky sessions_, is a load balancing strategy whereby a sequence of requests from a single client are consistently routed to the same application backend.
   446  Contour supports session affinity on a per-route basis with `loadBalancerPolicy` `strategy: Cookie`.
   447  
   448  ```yaml
   449  # httpproxy-sticky-sessions.yaml
   450  apiVersion: projectcontour.io/v1
   451  kind: HTTPProxy
   452  metadata:
   453    name: httpbin
   454    namespace: default
   455  spec:
   456    virtualhost:
   457      fqdn: httpbin.davecheney.com
   458    routes:
   459    - services:
   460      - name: httpbin
   461        port: 8080
   462      loadBalancerPolicy:
   463        strategy: Cookie
   464  ```
   465  
   466  Session affinity is based on the premise that the backend servers are robust, do not change ordering, or grow and shrink according to load.
   467  None of these properties are guaranteed by a Kubernetes cluster and will be visible to applications that rely heavily on session affinity.
   468  
   469  Any perturbation in the set of pods backing a service risks redistributing backends around the hash ring.
   470  
   471  ## Internal Redirects
   472  
   473  HTTPProxy supports handling 3xx redirects internally, that is capturing a configurable 3xx redirect response, synthesizing a new request, sending it to the upstream specified by the new route match, and returning the redirected response as the response to the original request.
   474  
   475  Internal redirects can be enabled in HTTPProxy by defining an `internalRedirectPolicy` on a route.
   476  
   477  ```yaml
   478  apiVersion: projectcontour.io/v1
   479  kind: HTTPProxy
   480  metadata:
   481   name: myservice
   482   namespace: prod
   483  spec:
   484   virtualhost:
   485     fqdn: foo.com
   486     routes:
   487       - conditions:
   488           - prefix: /download
   489         services:
   490           - name: foo
   491             port: 8080
   492         internalRedirectPolicy:
   493           maxInternalRedirects: 5
   494           redirectResponseCodes: [ 302 ]
   495           allowCrossSchemeRedirect: SafeOnly
   496           denyRepeatedRouteRedirect: true
   497  ```
   498  
   499  In this example, a sample redirect flow might look like this:
   500  
   501  1. Client sends a `GET` request for http://foo.com/download.
   502  2. Upstream `foo` returns a `302` response with `location: http://foo.com/myfile`.
   503  3. Envoy lookups a route for http://foo.com/myfile and sends a new `GET` request to the corresponding upstream with the additional request header `x-envoy-original-url: http://foo.com/download`.
   504  4. Envoy proxies the response data for http://foo.com/myfile to the client as the response to the original request.
   505  
   506  See [the API specification][9] and [Envoy's documentation][10] for more detail.
   507  
   508  [3]: /docs/{{< param version >}}/config/api/#projectcontour.io/v1.HTTPRequestRedirectPolicy
   509  [4]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-timeout
   510  [5]: https://godoc.org/time#ParseDuration
   511  [6]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-idle-timeout
   512  [7]: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/overview
   513  [8]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-field-config-core-v3-httpprotocoloptions-idle-timeout
   514  [9] /docs/{{< param version >}}/config/api/#projectcontour.io/v1.HTTPInternalRedirectPolicy
   515  [10] https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/http_connection_management.html#internal-redirects