Header Matching

The invertMatch attribute was introduced with Gloo, release 0.20.9. If you are using an earlier version, the attribute will not be available.

When configuring the matcher on a route, you may want to specify one or more Header Matchers to require headers with matching values be present on the request. Each header matcher has three attributes:

Setup

This guide assumes that you have installed Gloo into the gloo-system namespace and that glooctl is installed on your machine. For convenience, let’s also store the URL of the Gloo Gateway in a variable in your terminal:

export GATEWAY_URL=$(glooctl proxy url)

Let’s create a simple upstream for testing called json-upstream, that routes to a static site:


apiVersion: gloo.solo.io/v1
kind: Upstream
metadata:
  name: json-upstream
  namespace: gloo-system
spec:
  upstreamSpec:
    static:
      hosts:
        - addr: jsonplaceholder.typicode.com
          port: 80

glooctl create upstream static --static-hosts jsonplaceholder.typicode.com:80 --name json-upstream

Example

Let’s create a virtual service with several header match rules. For simplicity, we’ll set the path matcher to prefix on / to match all request paths:


apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: test-header
  namespace: gloo-system
spec:
  virtualHost:
    domains:
      - 'foo'
    routes:
      - matcher:
          headers:
            - name: header1
              value: value1
            - name: header2
            - name: header3
              regex: true
              value: "[a-z]{1}"
            - name: header4
              invertMatch: true
            - name: header5
              value: value5
              invertMatch: true
          prefix: /
        routeAction:
          single:
            upstream:
              name: json-upstream
              namespace: gloo-system


glooctl create vs --name test-header --namespace gloo-system --domains foo 
glooctl add route --name test-header --header "header1=value1" --header "header2=" --header "header3=[a-z]{1}" --path-prefix / --dest-name json-upstream

We can now make a curl request to the new virtual service and set valid values for each header. In this case,

Let’s send a request that satisfies all these criteria:

curl -v -H "Host: foo" -H "header1: value1" -H "header2: value2" -H "header3: v"  $GATEWAY_URL/posts

This returns a json list of posts.

If we use an incorrect value for header1, we’ll see a 404:

curl -v -H "Host: foo" -H "header1: othervalue" -H "header2: value2" -H "header3: v"  $GATEWAY_URL/posts

If we use a different value for header2, we’ll see all the posts:

curl -v -H "Host: foo" -H "header1: value1" -H "header2: othervalue" -H "header3: v"  $GATEWAY_URL/posts

If we use an invalid value for header3, we’ll get a 404:

curl -v -H "Host: foo" -H "header1: value1" -H "header2: value2" -H "header3: value3"  $GATEWAY_URL/posts

The invertMatch attribute in the last entry causes request to be matched only if it does not include a header named header4. If we send a request with that header, we’ll get a 404 response:

curl -v -H "Host: foo" -H "header1: value1" -H "header2: value2" -H "header3: v" -H "header4: value4"  $GATEWAY_URL/posts

The invertMatch attribute can be combined with value match specifications. Where header4 had no value spec, the inversion invalidated all possible values. The match constraints on header5, on the other hand, mean that if header5 is present, the request will only match if the value is not equal to value5. If we send a request with that value, we’ll get a 404 response:

curl -v -H "Host: foo" -H "header1: value1" -H "header2: value2" -H "header3: v" -H "header5: value5"  $GATEWAY_URL/posts

Summary

In this example, we added header matchers to a virtual service route. We used exact match and regex matchers for a header value, and also showed how to match on a header without any specific value.

Let’s cleanup the virtual service and upstream we used:


kubectl delete vs -n gloo-system test-header
kubectl delete upstream -n gloo-system json-upstream

glooctl delete vs test-header
glooctl delete upstream json-upstream