Bundle your APIs into API products
You deployed your OpenAPI apps and created ApiDocs so that Gloo can stitch together the APIs into a servable schema. Now, you want to bundle your APIs together into API products.
About API products
API products might represent an entire product with many APIs, such as a pet store, or a large feature within the product that you want to treat separately, such as a checkout cart. To bundle your APIs into an API product, you use a Gloo RouteTable custom resource.
By using a Gloo route table, you can automatically add apps via Kubernetes labels or specify them at more fine-grained levels. You also get more advanced networking control, such as matching, redirect, rewrite, direct response, and forwarding actions. This way, you can set up complex rules for how your API products behave under different circumstances.
Route tables allow you to choose the API product strategy that's right for your developer portal.
- One API product per developer portal: For smaller or test use cases, you might just have one API product that you want to expose in a developer portal. In this case, you can create just one Gloo route table to represent that API product. See Bundle your APIs into an API product.
- Multiple API products per developer portal: For many use cases, your developer portal exposes several API products. To support this setup, see Create a domain-level route table for multiple API products.
- API versioning and lifecycle management: Many times, you might have multiple versions of an API that you want to expose to end-users. With Gloo Platform's flexibile approach to portal metadata, you can provide support phases, compatibility, usage plans, terms of service, licensing, and other lifecycle management information for each API version. Then, you can bundle multiple API versions into a single API product. For more information, see Version your APIs.
The API products in a route table are exposed through a Gloo virtual gateway resource. Your end users can access these API products securely via the ingress gateway by logging into the developer portal frontend that you deploy later.
With the examples in this guide, you can build a flexible API product setup as shown in the following diagram.
- The APIs are the apps that you previously deployed, and represent the destinations that you can route requests to. Each app has a corresponding Gloo ApiDoc that defines the OpenAPI spec.
- Two route tables represent the API products that you want to create. These route tables send requests to the backing destinations in the previous step.
- The Tracks route table represents a single microservice, the
tracks
API. - The Petstore route table represents three microservices, the
pets
,store
, andusers
APIs. Gloo can stitch together these services into a single schema to bundle and share these APIs as a single API product in the developer portal.
- The Tracks route table represents a single microservice, the
- Another route table is used for the host,
api.example.com
, that you want to use for all your API products. This route table delegates to the Tracks and Petstore route tables to include both of those API products. - The virtual gateway routes ingress requests from your end users along the
api.example.com
host to the matching route table. In turn, theapi.example.com
route table forwards requests to the matching route tables for APIs in each API product.
Before you begin
- Optional: Review the About API products section to learn more about API products and the example setup that you can create by following this guide's steps.
- Create your APIs, including the Gloo ApiDocs that describe the stitched schema.
Step 1: Bundle your APIs into an API product
Create a route table for the apps that you previously deployed. This way, Gloo knows which backing APIs to use to serve information for requests along particular paths.
The following steps create two route tables.
- The Tracks route table represents a single microservice, the
tracks
API. - The Petstore route table represents three microservices, the
pets
,store
, andusers
APIs. Gloo can stitch together these services into a single schema to bundle and share these APIs as a single API product in the developer portal.
-
Decide on the information for your Tracks API product. At a minimum, each route table for a portal must include an
apiProductId
and anapiVersion
. You can also include other portal metadata, as shown in the following example. Later, your developer portal displays this information in the end-user facing API documentation. For more multiple versions of your APIs, see Version your APIs. For more information about each setting, see the API docs.portalMetadata: apiProductId: "tracks" apiProductDisplayName: "Catstronauts Course Tracks" apiVersion: "v1" title: "Catstronauts REST API" description: "REST API for Catstronauts to retrieve data for tracks, authors and modules." termsOfService: "You must authenticate to use this API! And other Terms of Service." contact: "support@example.com" license: "License info, such as MIT" lifecycle: "Supported" customMetadata: compatibility: "None"
-
Create a route table to represent an API Product for a single API, such as your
tracks
app.kubectl apply -f - << EOF apiVersion: networking.gloo.solo.io/v2 kind: RouteTable metadata: name: tracks-rt namespace: gloo-mesh-gateways labels: portal: dev-portal api: tracks spec: http: - name: tracks-api labels: usagePlans: dev-portal matchers: - uri: prefix: / forwardTo: pathRewrite: / destinations: - ref: name: tracks-rest-api namespace: tracks port: number: 5000 portalMetadata: apiProductId: "tracks" apiProductDisplayName: "Catstronauts Course Tracks" apiVersion: "v1" title: "Catstronauts REST API" description: "REST API for Catstronauts to retrieve data for tracks, authors and modules." termsOfService: "You must authenticate to use this API! And other Terms of Service." contact: "support@example.com" license: "License info, such as MIT" lifecycle: "Supported" customMetadata: compatibility: "None" EOF
Review the following table to understand this configuration. For more information, see the API docs.
Setting Description Namespace Create the route table in the same namespace, or import it into the same Gloo workspace as the ingress gateway. In this example, the route table is in the same namespace as the ingress gateway, gloo-mesh-gateways
.Labels Include labels to help select this route table with other portal resources later. This example has two labels. The portal: dev-portal
label can be used to associate this route table as part of thedev-portal
collection of Gloo resources, while theapi: tracks
label can be used to associate this route table more specifically with the Tracks API.HTTP name and labels Name your route and add a label that you can use to apply the policies of your usage plan to the route later. In this example, the tracks-api
route has ausagePlans: dev-portal
label.HTTP matchers and forwardTo
for the routeFor each app that you want to expose APIs for, define the route matchers
that you want the APIs to be available on. This example defines the/
route for thetracks-rest-api
. Then, these routes are available on the matching host, such asapi.example.com/
.Portal metadata A set of key-value pairs that describe your API, which you put together in the previous step. Later, your developer portal displays this information in the end-user facing API documentation. -
Decide on the information for your Pet Store API product, which is a collection of serveral microservices that you previously deployed. At a minimum, each route table for a portal must include an
apiProductId
and anapiVersion
. You can also include other portal metadata, as shown in the following example. Later, your developer portal displays this information in the end-user facing API documentation. For more information, see the API docs.portalMetadata: apiProductId: "petstore" apiProductDisplayName: "Pet Store" apiVersion: "v1" title: "Pet Store REST API" description: "Totally awesome API for all things pets!" termsOfService: "You must authenticate to use this API! And other Terms of Service." contact: "support@example.com" license: "License info, such as MIT" lifecycle: "Supported" customMetadata: compatibility: "None"
-
Create a route table that represents the Pet Store API product for your
pets
,users
, andstore
API microservices.kubectl apply -f - << EOF apiVersion: networking.gloo.solo.io/v2 kind: RouteTable metadata: name: petstore-rt namespace: gloo-mesh-gateways labels: portal: dev-portal api: petstore spec: http: - name: pets-api labels: usagePlans: dev-portal matchers: - uri: prefix: /pet forwardTo: destinations: - ref: name: pets-rest-api namespace: pets port: number: 5000 - name: users-api labels: usagePlans: dev-portal matchers: - uri: prefix: /user forwardTo: destinations: - ref: name: users-rest-api namespace: users port: number: 5000 - name: store-api labels: usagePlans: dev-portal matchers: - uri: prefix: /store forwardTo: destinations: - ref: name: store-rest-api namespace: store port: number: 5000 portalMetadata: apiProductId: "petstore" apiProductDisplayName: "Pet Store" apiVersion: "v1" title: "Pet Store REST API" description: "Totally awesome API for all things pets!" termsOfService: "You must authenticate to use this API! And other Terms of Service." contact: "support@example.com" license: "License info, such as MIT" lifecycle: "Supported" customMetadata: compatibility: "None" EOF
Review the following table to understand this configuration. For more information, see the description from the previous step and the API docs.
Setting Description HTTP name and labels Name your route and add a label that you can use to apply the policies of your usage plan to the route later. In this example, each route has a usagePlans: dev-portal
label.HTTP matchers and forwardTo
for the routeFor each app that you want to expose APIs for, define the route matchers
that you want the APIs to be available on. This example defines three routes:/pet
,/user
, and/store
. These routes correspond to three APIs that you previously deployed, which Gloo can then stitch together into a single schema to build the Petstore API product. Then, these routes are available on the matching host, such asapi.example.com/pet
,api.example.com/users
, orapi.example.com/store
.Portal metadata A set of key-value pairs that describe your API, which you put together in the previous step. Later, your developer portal displays this information in the end-user facing API documentation. -
To configure the domain that you want your API products exposed on, continue to the next step.
Step 2: Create a domain-level route table for multiple API products
For many use cases, your developer portal exposes several API products. To support this setup, you can create one overarching route table for the domain of your developer portal. Then, you can delegate matching routes along certain API paths to other route tables that represent that API product.
This way, you have one main route table for the domain that you can use to expose all of the API products that it includes, such as when you create a usage plan. You can easily add more API products by delegating to more route tables. You also still keep the flexibility to apply usage plans to the particular API product's route tables within the overarching domain's route table, for more granular control.
-
Create individual route tables for each API product that you want to expose.
-
Create a route table for the domain that you want your API products to be exposed on. This route table delegates the routing rules for matching HTTP routes to the route tables that you previously created. Note that the following example does not set any portal metadata, because that information is set per API product in the delegated route tables.
If you only want a single route table for one API product, just add the hosts and virtual gateway fields from the following spec example to each API product's route table.kubectl apply -f - << EOF apiVersion: networking.gloo.solo.io/v2 kind: RouteTable metadata: name: api-example-com-rt namespace: gloo-mesh-gateways spec: hosts: - api.example.com virtualGateways: - name: istio-ingressgateway namespace: gloo-mesh-gateways http: - matchers: - uri: prefix: /trackapi delegate: routeTables: - labels: api: tracks - matchers: - uri: prefix: /petstore delegate: routeTables: - labels: api: petstore EOF
Review the following table to understand this configuration. For more information, see the API docs.
Setting Description Namespace Create the route table in the same namespace or import it into the same Gloo workspace as the ingress gateway. In this example, the route table is in the same namespace as the ingress gateway, gloo-mesh-gateways
.Hosts Add the host domains that you want the API products to be exposed on, such as api.example.com
.Virtual gateway Select the ingress gateway with the host that you want to use to expose your apps’ APIs. In this example, the default ingress gateway is selected. HTTP matchers and delegations For each API product that you want to expose on the host domain, set up matchers and delegated route tables. In this example, requests that match /trackapi
are delegated to the Tracks route table. Requests that match/petstore
are delegated to the Petstore route table. -
To create the virtual gateway for the domain that you want your API products to be exposed on, continue to the next step.
Step 3: Create the virtual gateway for your domain
To expose your API products, configure the ingress gateway to listen on a host and forward requests to the route tables.
The following example configures a simple HTTP gateway. For more examples such as HTTPS/TLS, see Configure gateway listeners.
-
Create individual route tables for each API product that you want to expose.
-
Optional: Create a domain-level route table if you want to expose several API products on the same domain.
-
Create a virtual gateway for the host domain that you want to expose your API products on.
kubectl apply -f - << EOF apiVersion: networking.gloo.solo.io/v2 kind: VirtualGateway metadata: name: istio-ingressgateway namespace: gloo-mesh-gateways spec: listeners: - port: number: 80 http: {} allowedRouteTables: - host: api.example.com workloads: - selector: labels: istio: ingressgateway cluster: $CLUSTER_NAME EOF
Review the following table to understand this configuration. For more information, see the API docs.
Setting Description Listener's allowed route tables Add the host domain that matches the route table for the API products that you want to expose. In this example, the api.example.com
matches the host in the domain-level route table that you created to expose together your two API products, Tracks and Petstore. -
To verify your setup, continue to the next step.
Step 4: Verify your setup
You can use the Gloo UI and the terminal to verify your API product routing setup.
Gloo UI
Review the stitched API schemas for your API products in the Gloo UI.
- Launch the Gloo UI.
meshctl dashboard
- Click the API tab and verify that you have two API products for both of the route tables that you created,
petstore-rt
andtracks-rt
. - Click one of the API products and verify that you can see the following information:
- The API Schema that describes your app's REST APIs. You can also click View OpenAPI to see the stitched schema of the API product in JSON format.
- The Applied to Destinations shows the backing destinations of all of the apps that are included in the API product.
- Note that the Portals are not shown yet, because you have not created the Portal resource.
Terminal
Verify that you can access your APIs through the ingress gateway on the host domain that you configured.
-
Get the external address of the ingress gateway. If you deployed your ingress gateway in a different namespace or with a different version, update the command.
export INGRESS_GW_IP=$(kubectl get svc -n gloo-mesh-gateways istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo $INGRESS_GW_IP
export INGRESS_GW_IP=$(kubectl get svc -n gloo-mesh-gateways istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') echo $INGRESS_GW_IP
Note: Depending on your environment, you might see
<pending>
instead of an external IP address. For example, if you are testing locally in kind or minikube, or if you have insufficent permissions in your cloud platform, you can instead port-forward the service port of the ingress gateway:kubectl -n gloo-mesh-gateways port-forward deploy/istio-ingressgateway-1-18-2 8081
-
In your terminal, send a curl request to both of the API products that you set up. Note that the routes are not yet secured. You secure the routes with rate limiting and external auth policies later as part of your portal's usage plan.
api.example.com
is the host that you set in both the domain-level route table and the virtual gateway./trackapi
is the prefix that you set in both the domain-level route table to delegate requests to thetracks-rt
route table./tracks
is an endpoint from the tracks API in thetracks-rt
route table.
curl -v --resolve api.example.com:80:${INGRESS_GW_IP} http://api.example.com/trackapi/tracks
Example output:
< HTTP/1.1 200 OK ... [ { "id": "c_0", "thumbnail": "https://res.cloudinary.com/dety84pbu/image/upload/v1598465568/nebula_cat_djkt9r.jpg", "topic": "Cat-stronomy", "authorId": "cat-1", "title": "Cat-stronomy, an introduction", "description": "Curious to learn what Cat-stronomy is all about? Explore the planetary and celestial alignments and how they have affected our space missions.", "numberOfViews": 163, "createdAt": "2018-09-10T07:13:53.020Z", "length": 2377, "modulesCount": 10, "modules": [ "l_0", "l_1", "l_2", "l_3", "l_4", "l_5", "l_6", "l_7", "l_8", "l_9" ] }, ...
api.example.com
is the host that you set in both the domain-level route table and the virtual gateway./petstore
is the prefix that you set in both the domain-level route table to delegate requests to thepetstore-rt
route table./pet
,/user
, and/order
are endpoints from the stitched API schema of thepetstore-rt
route table. Note that, even though these APIs are served by different backing destinations, they are all available under the same/petstore
prefix for the single route table that you set up for this Petstore API product.
curl -v --resolve api.example.com:80:${INGRESS_GW_IP} http://api.example.com/petstore/pet curl -v --resolve api.example.com:80:${INGRESS_GW_IP} http://api.example.com/petstore/user curl -v --resolve api.example.com:80:${INGRESS_GW_IP} http://api.example.com/petstore/store/order
Example output:
< HTTP/1.1 200 OK ... [ { "id": 1, "name": "Barky", "photoUrls": [ "image1.jpg" ], ...
Next steps
With API products in place, you are one step closer to sharing your APIs with the world.
Next, you can work with your Portal Admin to protect your APIs by creating usage plans.
When you are done with trying out Portal, you can clean up all of the resources that you created.