Skip to content

Function Routing

What you'll need

If you haven't already deployed Gloo and the example Swagger service on Docker, go back to the first tutorial.

Now that we've seen the traditional routing functionality of Gloo (i.e. API-to-service), let's try doing some function routing.

Let's take a look at the upstream that was created for our petstore service:

glooctl upstream get petstore -o yaml

functions:
- name: addPet
  spec:
    body: '{"id": {{ default(id, "") }},"name": "{{ default(name, "")}}","tag": "{{
      default(tag, "")}}"}'
    headers:
      :method: POST
      Content-Type: application/json
    path: /api/pets
- name: deletePet
  spec:
    body: ""
    headers:
      :method: DELETE
    path: /api/pets/{{ default(id, "") }}
- name: findPetById
  spec:
    body: ""
    headers:
      :method: GET
    path: /api/pets/{{ default(id, "") }}
- name: findPets
  spec:
    body: ""
    headers:
      :method: GET
    path: /api/pets?tags={{default(tags, "")}}&limit={{default(limit, "")}}
...

We can see there are functions on our petstore upstream. These functions were populated automatically by the function-discovery pod. You can see the function discovery service in action by running docker logs

docker logs gloo-tutorial_function-discovery_1

Remember to replace the container based on the output of docker ps

The function spec you see on the functions listed above belongs to the transformation plugin. This powerful plugin configures Gloo's request/response transformation Envoy filter to perform transform requests to the structure expected by our petstore app.

In a nutshell, this plugin takes Inja templates for HTTP body, headers, and path as its parameters (documented in the plugin spec and transforms incoming requests from those templates. Parameters for these templates can come from the request body (if it's JSON), or they can come from parameters specified in the extensions on a route.

Let's see how this plugin works by creating some routes to these functions in the next section.

Steps

Step 1

Start by creating the route with glooctl:

glooctl route create \
  --path-exact /petstore/findPet \
  --upstream petstore \
  --function findPetById

You should see the output:

Using virtual service: default
+-------------------+------------+------+--------+----------+-------------+-----------+
|      MATCHER      |    TYPE    | VERB | HEADER | UPSTREAM |  FUNCTION   | EXTENSION |
+-------------------+------------+------+--------+----------+-------------+-----------+
| /petstore/list    | Exact Path | *    |        | petstore |             |           |
| /petstore/findPet | Exact Path | *    |        | petstore | findPetById |           |
+-------------------+------------+------+--------+----------+-------------+-----------+

Notice that, unlike the previous tutorial, we're passing an extra argument to glooctl: --function findPetById.

Let's go ahead and test the route using curl:

curl http://127.0.0.1:8080/petstore/findPet

[{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]

This is not working as find pet, but as list. Looking again at the function findPetById, you will notice the template wants a variable called id:

- name: findPetById
  spec:
    body: ""
    headers:
      :method: GET
    path: /api/pets/{{id}}

Step 2

Try the request again, but now add a JSON body with the parameter specified by name:

curl http://127.0.0.1:8080/petstore/findPet -d '{"id": 1}'

{"id":1,"name":"Dog","status":"available"}

Great! We just called our first function through Gloo.

  1. Parameters can also come from headers. Let's tell Gloo to look for id in a custom header.

Let's take a look at the route we created:

glooctl route get -o yaml

Using virtual service: default
---
prefix_rewrite: /api/pets
request_matcher:
  path_exact: /petstore/list
single_destination:
  upstream:
    name: petstore

---
request_matcher:
  path_exact: /petstore/findPet
single_destination:
  function:
    function_name: findPetById
    upstream_name: petstore

We need to add an extension to this route that tells Gloo how to grab template parameters from the request.

Add parameters to the route's extensions like so:

cat <<EOF | glooctl route update --old-path-exact /petstore/findPet --old-upstream petstore --old-function findPetById --path-exact /petstore/findPet --upstream petstore --function findPetById --extensions -
parameters:
  headers:
    x-pet: '{id}'
EOF

Now Gloo knows to look for the parameter named id in a header called pet.

Try curl again, this time with the new header:

curl http://127.0.0.1:8080/petstore/findPet -H "x-pet: 1"

{"id":1,"name":"Dog","status":"available"}

Tutorials for more advanced use-cases are coming soon. In the meantime, please see our plugin documentation for a list of available plugins and their configuration options.