REST Endpoint
In this guide we will create a route to a specific REST endpoint.
Setup
Let’s configure Gloo Gateway to route to a single, static Upstream. In this case, we’ll route requests through Gloo Gateway to the JSON testing API available at http://jsonplaceholder.typicode.com/
.
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
If you haven’t already deployed Gloo Gateway and an example swagger service on Kubernetes, go back to the Hello World guide and run through it to get the Pet Store application deployed.
Configure function routing
Now that we’ve seen the traditional routing functionality of Gloo Gateway (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 --output 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 -n gloo-system
.
The function spec you see on the functions listed above is populated by the transformation plugin. This powerful plugin configures Gloo Gateway’s request/response transformation Envoy filter, transforming requests to the structure expected by our Pet Store application.
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.
Create the route
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 hello world tutorial, we’re passing an extra argument to glooctl --rest-function-name findPetById
.
Test the route
Let’s go ahead and test the route using curl
:
curl $(glooctl proxy 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}}
Try the request again, but now add a JSON body which includes the id
parameter:
curl $(glooctl proxy url)/petstore/findPet -d '{"id": 1}'
{"id":1,"name":"Dog","status":"available"}
curl $(glooctl proxy url)/petstore/findPet -d '{"id": 2}'
{"id":2,"name":"Cat","status":"pending"}
Great! We just called our first function through Gloo Gateway.
Pass parameters in a header
Parameters can also come from headers. Let’s tell Gloo Gateway to look for id
in a header.
Let’s take a look at the route we created:
glooctl get virtualservice --output yaml
---
metadata:
name: default
namespace: gloo-system
resourceVersion: "33083"
status:
reportedBy: gateway
state: Accepted
subresourceStatuses:
'*v1.Proxy gloo-system gateway-proxy':
reportedBy: gloo
state: Accepted
virtualHost:
domains:
- '*'
routes:
- matchers:
- exact: /petstore/findPet
routeAction:
single:
destinationSpec:
rest:
functionName: findPetById
parameters: {}
upstream:
name: default-petstore-8080
namespace: gloo-system
We can tell Gloo Gateway to grab the template parameters from the request with a flag called rest-parameters
like this:
glooctl add route \
--path-prefix /petstore/findWithId/ \
--dest-name default-petstore-8080 \
--rest-function-name findPetById \
--rest-parameters ':path=/petstore/findWithId/{id}'
Try curl
again, this time with the new header:
curl $(glooctl proxy url)/petstore/findWithId/1
{"id":1,"name":"Dog","status":"available"}
You may be asking, “Why are you calling that a header, it’s not a header”? We’re actually calling the service with a path parameter, but in HTTP2 a header called :path
is used to pass the path information around. At the moment, since Envoy has built everything internally around HTTP2, we can use this :path
header to pull template parameters. We could have used another header like x-gloo
to pass in and then create our rest-parameters
with the x-gloo
header and accomplish the same thing. We’ll leave that as an exercise to the reader.
Next Steps
In this guide you saw how to use function routing for a REST endpoint. You can learn more about routing and matchers in our guides about destination selection.