Header Matching

The route rules in a Virtual Service can use header matching rules to match requests to routes based on the contents of the headers. 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:

When you use header matchers, you must also specify a prefix matcher. Note that the path you define in prefix matcher cannot contain any hyphens (-).

In this guide, we’re going to take a closer look at an example Virtual Service that uses multiple headers to match requests. We’ll begin by creating an Upstream and then creating the Virtual Service to route requests to that Upstream based on the headers submitted as part of the request.


Setup

If you have not yet deployed Gloo Edge, you can start by following the directions contained within the guide Installing Gloo Edge on Kubernetes.

This guide also assumes that you are running Gloo Edge in a Kubernetes cluster. Each example can be adapted to alternative deployments, such as using the HashiCorp stack of Nomad, Consul, and Vault.

This guide assumes that you have deployed Gloo to the gloo-system namespace and that the glooctl command line utility is installed on your machine. glooctl provides several convenient functions to view, manipulate, and debug Gloo resources; in particular, it is worth mentioning the following command, which we will use each time we need to retrieve the URL of the Gloo Gateway that is running inside your cluster:

glooctl proxy url

Create an Upstream

First we are going to 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:
  static:
    hosts:
      - addr: jsonplaceholder.typicode.com
        port: 80

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

Create a Virtual Service

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. Note that when you use header matchers, you must also specify a prefix matcher, and the path you define in prefix matcher cannot contain any hyphens (-).


apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: test-header
  namespace: gloo-system
spec:
  virtualHost:
    domains:
      - 'foo'
    routes:
      - matchers:
         - 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
        options:
          autoHostRewrite: true

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" \
  -H "header5: x" $(glooctl proxy 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"  \
  -H "header5: x" $(glooctl proxy 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"  \
  -H "header5: x" $(glooctl proxy 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"  \
  -H "header5: x" $(glooctl proxy url)/posts

The invertMatch attribute for header4 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"  -H "header5: x" $(glooctl proxy 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 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" $(glooctl proxy url)/posts

Summary

In this guide, 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

Next Steps

Header matching rules are not the only rules available for routing decisions. We recommend checking out any of the following guides next: