Path Matching

There are three options to do HTTP path matching. You can specify only one of the following three options within any given route matcher spec:

Setup

This guide assumes you’ve installed Gloo into the gloo-system namespace, and glooctl is installed to your machine. Let’s also make sure $GATEWAY_URL is set 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

Prefix Matching

To see how prefix matching is configured, let’s create a virtual service and route to that upstream:


apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: test-prefix
  namespace: gloo-system
spec:
  virtualHost:
    domains:
      - 'foo'
    name: gloo-system.default
    routes:
      - matcher:
          prefix: /
        routeAction:
          single:
            upstream:
              name: json-upstream
              namespace: gloo-system

glooctl create vs --name test-prefix --namespace gloo-system --domains foo
glooctl add route --name test-prefix --path-prefix / --dest-name json-upstream

Since we are using the foo domain, if we make a curl request and don’t provide the Host header, it will 404.

curl -v $GATEWAY_URL/posts

This will print a 404 response containing:

< HTTP/1.1 404 Not Found
< date: Wed, 31 Jul 2019 17:20:23 GMT
< server: envoy
< content-length: 0

If we pass the Host header, we will successfully get results.

curl -H "Host: foo" $GATEWAY_URL/posts
[
  {
    "userId": 1,
    "id": 1,
    "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
    "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
  },
  {
    "userId": 1,
    "id": 2,
    "title": "qui est esse",
    "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
  },
  {
    "userId": 1,
    "id": 3,
    "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
    "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
  },
  ...
]

A request to the /path matches on the prefix / and is routed to the upstream at jsonplaceholder.typicode.com:80.

Let’s clean up this virtual service and look at exact matchers next.


kubectl delete vs -n gloo-system test-prefix

glooctl delete vs --name test-prefix

Exact matching

Now let’s configure an exact match virtual service to route to our test upstream, first matching on /:


apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: test-exact-1
  namespace: gloo-system
spec:
  virtualHost:
    domains:
      - 'foo'
    name: gloo-system.default
    routes:
      - matcher:
          exact: /
        routeAction:
          single:
            upstream:
              name: json-upstream
              namespace: gloo-system

glooctl create vs --name test-exact-1 --namespace gloo-system --domains foo
glooctl add route --name test-exact-1 --path-exact / --dest-name json-upstream

Now a request to path /posts will not match and should return a 404:

curl -v -H "Host: foo" $(glooctl proxy url)/posts

Let’s delete that virtual service:


kubectl delete vs -n gloo-system test-exact-1

glooctl delete vs --name test-exact-1

Now let’s create a virtual service with a route that has an exact match on /posts:


apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: test-exact-2
  namespace: gloo-system
spec:
  virtualHost:
    domains:
      - 'foo'
    name: gloo-system.default
    routes:
      - matcher:
          exact: /posts
        routeAction:
          single:
            upstream:
              name: json-upstream
              namespace: gloo-system

glooctl create vs --name test-exact-2 --namespace gloo-system --domains foo
glooctl add route --name test-exact-2 --path-exact /posts --dest-name json-upstream
curl -v -H "Host: foo" $(glooctl proxy url)/posts

Now returns results.

[
  {
    "userId": 1,
    "id": 1,
    "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
    "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
  },
  {
    "userId": 1,
    "id": 2,
    "title": "qui est esse",
    "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
  },
  {
    "userId": 1,
    "id": 3,
    "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
    "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
  },
  ...
]

Let’s delete this virtual service:


kubectl delete vs -n gloo-system test-exact-2

glooctl delete vs --name test-exact-2

Regex Matching

Finally, let’s create a route that uses a regex matcher, in this case matching on any 5-character path:


apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: test-regex
  namespace: gloo-system
spec:
  virtualHost:
    domains:
      - 'foo'
    name: gloo-system.default
    routes:
      - matcher:
          regex: /[a-z]{5}
        routeAction:
          single:
            upstream:
              name: json-upstream
              namespace: gloo-system

glooctl create vs --name test-regex --namespace gloo-system --domains foo
glooctl add route --name test-regex --path-regex /[a-z]{5} --dest-name json-upstream

This request will return a 404 because the path /comments is more than 5 characters:

curl -v -H "Host: foo" $GATEWAY_URL/comments

However, the following requests will both succeed:

curl -v -H "Host: foo" $(glooctl proxy url)/posts
curl -v -H "Host: foo" $(glooctl proxy url)/todos

Let’s delete this virtual service:


kubectl delete vs -n gloo-system test-regex

glooctl delete vs --name test-regex

Summary

In this tutorial, we created a static upstream and added a route on a virtual service to point to it. We learned how to use all 3 types of matchers allowed by Gloo when determining if a route configuration matches a request path: prefix, exact, and regex.

Let’s cleanup the test upstream we used:


kubectl delete upstream -n gloo-system json-upstream

glooctl delete upstream json-upstream