What you'll need

If you haven't already deployed Gloo and the example swagger service on kubernetes, 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 get upstream default-petstore-8080 -o yaml

     ...
         serviceSpec:
           rest:
             swaggerInfo:
               url: http://petstore.default.svc.cluster.local:8080/swagger.json
             transformations:
               addPet:
                 body:
                   text: '{"id": {{ default(id, "") }},"name": "{{ default(name, "")}}","tag":
                     "{{ default(tag, "")}}"}'
                 headers:
                   :method:
                     text: POST
                   :path:
                     text: /api/pets
                   content-type:
                     text: application/json
               deletePet:
                 headers:
                   :method:
                     text: DELETE
                   :path:
                     text: /api/pets/{{ default(id, "") }}
                   content-type:
                     text: application/json
               findPetById:
                 body: {}
                 headers:
                   :method:
                     text: GET
                   :path:
                     text: /api/pets/{{ default(id, "") }}
                   content-length:
                     text: "0"
                   content-type: {}
                   transfer-encoding: {}
               findPets:
                 body: {}
                 headers:
                   :method:
                     text: GET
                   :path:
                     text: /api/pets?tags={{default(tags, "")}}&limit={{default(limit,
                       "")}}
                   content-length:
                     text: "0"
                   content-type: {}
                   transfer-encoding: {}
     ...

We can see there are functions on our default-petstore-8080 upstream. These functions were populated automatically by the discovery pod. You can see the function discovery service in action by running kubectl logs -l gloo=discovery

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

  1. Start by creating the route with glooctl:

    glooctl add route \
      --path-exact /petstore/findPet \
      --dest-name default-petstore-8080 \
      --rest-function-name findPetById
    

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

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

    export GATEWAY_URL=$(glooctl gateway url)
    curl ${GATEWAY_URL}/petstore/findPet
    
    [{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]
    

    Looking again at the function findPetById, you'll notice the template wants a variable called id:

     - name: findPetById
       spec:
         body: ""
         headers:
           :method: GET
         path: /api/pets/{{id}}
    
  2. Try the request again, but now add a JSON body which includes the id parameter:

    curl ${GATEWAY_URL}/petstore/findPet -d '{"id": 1}'
    
    {"id":1,"name":"Dog","status":"available"}
    
    curl ${GATEWAY_URL}/petstore/findPet -d '{"id": 2}'
    
    {"id":2,"name":"Cat","status":"pending"}
    

    Great! We just called our first function through Gloo.


  3. 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 get virtualservice -o yaml
    
    ---
    metadata:
      name: default
      namespace: gloo-system
      resourceVersion: "6939"
    status:
      reportedBy: gateway
      state: Accepted
      subresourceStatuses:
        '*v1.Proxy gloo-system gateway-proxy':
          reportedBy: gloo
          state: Accepted
    virtualHost:
      domains:
      - '*'
      name: gloo-system.default
      routes:
      - matcher:
          exact: /petstore/findPet
        routeAction:
          single:
            destinationSpec:
              rest:
                functionName: findPetById
                parameters: {}
            upstream:
              name: default-petstore-8080
              namespace: gloo-system
    

    We need to add a route with a parameter that tells Gloo how to grab template parameters from the request.

    Add parameters to the route's extensions like so:

    glooctl add route \
      --path-prefix /petstore/findWithId/ \
      --dest-name default-petstore-8080 \
      --rest-function-name findPetById \
      --rest-parameters ':path=/petstore/findWithId/{id}'
    

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

    Try curl again, this time with the new header:

    curl ${GATEWAY_URL}/petstore/findWithId/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.