Pubish APIs from CRDs
Old documentation for Hub v1
Kubernetes only!
This is a more advanced topic and requires deeper knowledge of Kubernetes!
Introduction¶
In this tutorial, you'll learn how to use Kubernetes Custom Resource Definitions with Traefik Hub to manage and publish APIs.
For the purpose of this tutorial, you will use domains generated by Traefik Hub for the API Gateway and Portal.
By the end of this tutorial, you'll have learned how to:
- Deploy APIs with CRDs
- Configures access and permissions of APIs and API collections
- Configure an API Gateway
- Expose an API Portal
- Use curl or HTTPIe for sending API requests
Before you begin¶
Before getting started, make sure you have the following:
- An account registered on the Traefik Hub platform
- A Kubernetes cluster
kubectl
installed and configured- curl or HTTPIe installed
1. Install Traefik and the Traefik Hub Agent¶
In the first step, you will set up Traefik and the Traefik Hub Agent.
Login to Traefik Hub and create your first Agent by selecting Install my first Traefik Hub Agent.
Choose Kubernetes as platform.
1.1 Add the Traefik Helm repository¶
Copy the first code block into your terminal and select Enter.
1.2 Installing Traefik¶
This command will:
- Upgrade the chart to the latest version
- Will install Traefik via the chart into the namespace
hub-agent
Copy the code block into your terminal and hit Enter.
1.3. Installing the Traefik Hub Agent¶
Copy and paste the configuration shown in the Traefik Hub UI into the CLI.
1.4 Save the token¶
Save the token in a secure place!
Select Copy and save your token.
Once you are done, select Configuration Done.
2. Configure the Traefik Hub Agent¶
Name the Agent to api-demo
and select Save, followed by selecting Go to the Agent Details.
3. Prepare the demo¶
Create a directory called hub-demo
, this will be your working directory for this tutorial.
All APIs will be deployed into the apps namespace.
In this step, you will create this namespace.
Create a file with the name namespace.yaml
in your hub-demo
directory with the following content:
---
apiVersion: v1
kind: Namespace
metadata:
name: apps
Use kubectl
to deploy it:
kubectl apply -f namespace.yaml
4. Deploy the demo APIs¶
Now, that you have created the namespace for your API apps, it's time to deploy the APIs.
Customers API¶
In your hub-demo
directory, create a new directory called customer
and change into it.
Now create the following YAML
files:
api.yaml
---
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: customer-api
namespace: apps
labels:
area: customers
module: crm
spec:
pathPrefix: "/customers"
service:
openApiSpec:
path: /openapi.yaml
port:
number: 3000
name: customer-app
port:
number: 3000
customer.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: customer-data
namespace: apps
data:
api.json: |
{
"customers": [
{ "id": 1, "firstName": "John", "lastName": "Doe", "points": 100, "status": "bronze" },
{ "id": 2, "firstName": "Jane", "lastName": "Doe", "points": 200, "status": "silver" },
{ "id": 3, "firstName": "John", "lastName": "Smith", "points": 300, "status": "gold" }
]
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: customer-app
namespace: apps
spec:
replicas: 1
selector:
matchLabels:
app: customer-app
template:
metadata:
labels:
app: customer-app
spec:
containers:
- name: api
image: douglasdtm/json-server:openapi
args: ["--watch", "/api/api.json", "--static", "/public"]
imagePullPolicy: IfNotPresent
volumeMounts:
- name: api-data
mountPath: /api
- name: openapi
mountPath: /public
volumes:
- name: api-data
configMap:
name: customer-data
- name: openapi
configMap:
name: customer-apispec
---
apiVersion: v1
kind: Service
metadata:
name: customer-app
namespace: apps
labels:
app: customer-app
spec:
type: ClusterIP
ports:
- port: 3000
name: api
selector:
app: customer-app
spec.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: customer-apispec
namespace: apps
data:
openapi.yaml: |
openapi: "3.0.0"
info:
version: 1.0.0
title: Customers
description: OpenAPI specification based on Swagger Petstore (https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore.yaml).
servers:
- url: https://api.traefik.localhost
paths:
/customers:
get:
summary: Get customers
operationId: getCustomers
tags:
- customers
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
maximum: 100
format: int32
responses:
'200':
description: A paged array of customers
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Customers"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a customer
operationId: createCustomer
tags:
- customers
responses:
'201':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/customers/{customerId}:
get:
summary: Info for a specific customer
operationId: showCustomerById
tags:
- customers
parameters:
- name: customerId
in: path
required: true
description: The id of the customer
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Customer"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
put:
summary: Update a customer
operationId: updateCustomer
tags:
- customers
parameters:
- name: customerId
in: path
required: true
description: The id of the customer
schema:
type: string
responses:
'200':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
delete:
summary: Delete a customer
operationId: deleteCustomer
tags:
- customers
parameters:
- name: customerId
in: path
required: true
description: The id of the customer
schema:
type: string
responses:
'200':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Customer:
type: object
required:
- id
- firstName
- lastName
properties:
id:
type: integer
format: int64
firstName:
type: string
lastName:
type: string
points:
type: integer
format: int64
status:
type: string
Customers:
type: array
maxItems: 100
items:
$ref: "#/components/schemas/Customer"
Error:
type: object
required:
- message
properties:
message:
type: string
The following kubectl
commands will deploy the API:
kubectl apply -f api.yaml \
-f customer.yaml \
-f spec.yaml
Employee API¶
Go back into your hub-demo
directory, and create a new directory called employee
.
Once you have created it, change into it and create the following files:
api.yaml
---
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: employee-api
namespace: apps
labels:
area: internal
module: crm
spec:
pathPrefix: "/employees"
service:
openApiSpec:
path: /openapi.yaml
port:
number: 3000
name: employee-app
port:
number: 3000
employee.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: employee-data
namespace: apps
data:
api.json: |
{
"employees": [
{ "id": 1, "firstName": "John", "lastName": "Doe", "role": "pilot", "homeAirport": "RIC" },
{ "id": 2, "firstName": "Jane", "lastName": "Doe", "role": "engineer", "homeAirport": "CDG" },
{ "id": 3, "firstName": "John", "lastName": "Smith", "role": "attendant", "homeAirport": "DTW" }
]
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: employee-app
namespace: apps
spec:
replicas: 1
selector:
matchLabels:
app: employee-app
template:
metadata:
labels:
app: employee-app
spec:
containers:
- name: api
image: douglasdtm/json-server:openapi
args: ["--watch", "/api/api.json", "--static", "/public"]
imagePullPolicy: IfNotPresent
volumeMounts:
- name: api-data
mountPath: /api
- name: openapi
mountPath: /public
volumes:
- name: api-data
configMap:
name: employee-data
- name: openapi
configMap:
name: employee-apispec
---
apiVersion: v1
kind: Service
metadata:
name: employee-app
namespace: apps
labels:
app: employee-app
spec:
type: ClusterIP
ports:
- port: 3000
name: api
selector:
app: employee-app
spec.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: employee-apispec
namespace: apps
data:
openapi.yaml: |
openapi: "3.0.0"
info:
version: 1.0.0
title: Employees
description: OpenAPI specification based on Swagger Petstore (https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore.yaml).
servers:
- url: https://api.traefik.localhost
paths:
/employees:
get:
summary: Get employees
operationId: getEmployees
tags:
- employees
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
maximum: 100
format: int32
responses:
'200':
description: A paged array of employees
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Employees"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a employee
operationId: createEmployee
tags:
- employees
responses:
'201':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/employees/{employeeId}:
get:
summary: Info for a specific employee
operationId: showEmployeeById
tags:
- employees
parameters:
- name: employeeId
in: path
required: true
description: The id of the employee
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Employee"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
put:
summary: Update an employee
operationId: updateEmployee
tags:
- employees
parameters:
- name: employeeId
in: path
required: true
description: The id of the employee
schema:
type: string
responses:
'200':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
delete:
summary: Delete a employee
operationId: deleteEmployee
tags:
- employees
parameters:
- name: employeeId
in: path
required: true
description: The id of the employee
schema:
type: string
responses:
'200':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Employee:
type: object
required:
- id
- firstName
- lastName
properties:
id:
type: integer
format: int64
firstName:
type: string
lastName:
type: string
role:
type: string
homeAirport:
type: string
Employees:
type: array
maxItems: 100
items:
$ref: "#/components/schemas/Employee"
Error:
type: object
required:
- message
properties:
message:
type: string
The following kubectl
commands will deploy the API:
kubectl apply -f api.yaml \
-f employee.yaml \
-f spec.yaml
Flight API¶
Go back into your hub-demo
directory, and create a new directory called flight
.
Once you have created it, change into it and create the following files:
api.yaml
---
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: flight-api
namespace: apps
labels:
area: flights
module: erp
spec:
pathPrefix: "/flights"
service:
openApiSpec:
path: /openapi.yaml
port:
number: 3000
name: flight-app
port:
number: 3000
flight.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: flight-data
namespace: apps
data:
api.json: |
{
"flights": [
{ "id": 1, "code": "TL123", "src": "JFK", "dest": "CDG" },
{ "id": 2, "code": "TL234", "src": "CDG", "dest": "JFK" },
{ "id": 3, "code": "TL345", "src": "CDG", "dest": "LYS" }
]
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: flight-app
namespace: apps
spec:
replicas: 1
selector:
matchLabels:
app: flight-app
template:
metadata:
labels:
app: flight-app
spec:
containers:
- name: api
image: douglasdtm/json-server:openapi
args: ["--watch", "/api/api.json", "--static", "/public"]
imagePullPolicy: IfNotPresent
volumeMounts:
- name: api-data
mountPath: /api
- name: openapi
mountPath: /public
volumes:
- name: api-data
configMap:
name: flight-data
- name: openapi
configMap:
name: flight-apispec
---
apiVersion: v1
kind: Service
metadata:
name: flight-app
namespace: apps
labels:
app: flight-app
spec:
type: ClusterIP
ports:
- port: 3000
name: api
selector:
app: flight-app
spec.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: flight-apispec
namespace: apps
data:
openapi.yaml: |
openapi: "3.0.0"
info:
version: 1.0.0
title: Flights
description: OpenAPI specification based on Swagger Petstore (https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore.yaml).
servers:
- url: https://api.traefik.localhost
paths:
/flights:
get:
summary: Get flights
operationId: gettFlights
tags:
- flights
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
maximum: 100
format: int32
responses:
'200':
description: A paged array of flights
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Flights"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a flight
operationId: createFlight
tags:
- flights
responses:
'201':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/flights/{flightId}:
get:
summary: Info for a specific flight
operationId: showFlightById
tags:
- flights
parameters:
- name: flightId
in: path
required: true
description: The id of the flight
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Flight"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
put:
summary: Update a flight
operationId: updateFlight
tags:
- flights
parameters:
- name: flightId
in: path
required: true
description: The id of the flight
schema:
type: string
responses:
'200':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
delete:
summary: Delete a flight
operationId: deleteFlight
tags:
- flights
parameters:
- name: flightId
in: path
required: true
description: The id of the flight
schema:
type: string
responses:
'200':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Flight:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
code:
type: string
source:
type: string
destination:
type: string
Flights:
type: array
maxItems: 100
items:
$ref: "#/components/schemas/Flight"
Error:
type: object
required:
- message
properties:
message:
type: string
The following kubectl
commands will deploy the API:
kubectl apply -f api.yaml \
-f flight.yaml \
-f spec.yaml
Ticket API¶
Go back into your hub-demo
directory, and create a new directory called ticket
.
Once you have created it, change into it and create the following files:
api.yaml
---
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: ticket-api
namespace: apps
labels:
area: support
module: crm
spec:
pathPrefix: "/tickets"
service:
openApiSpec:
path: /openapi.yaml
port:
number: 3000
name: ticket-app
port:
number: 3000
ticket.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ticket-data
namespace: apps
data:
api.json: |
{
"tickets": [
{ "id": 1, "flightCode": "TL123", "fare": 500, "class": "first", "available": 5, "total": 20 },
{ "id": 2, "flightCode": "TL234", "fare": 200, "class": "economy", "available": 2, "total": 5 },
{ "id": 3, "flightCode": "TL345", "fare": 300, "class": "business", "available": 3, "total": 10 }
]
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ticket-app
namespace: apps
spec:
replicas: 1
selector:
matchLabels:
app: ticket-app
template:
metadata:
labels:
app: ticket-app
spec:
containers:
- name: api
image: douglasdtm/json-server:openapi
args: ["--watch", "/api/api.json", "--static", "/public"]
imagePullPolicy: IfNotPresent
volumeMounts:
- name: api-data
mountPath: /api
- name: openapi
mountPath: /public
volumes:
- name: api-data
configMap:
name: ticket-data
- name: openapi
configMap:
name: ticket-openapi
---
apiVersion: v1
kind: Service
metadata:
name: ticket-app
namespace: apps
labels:
app: ticket-app
spec:
type: ClusterIP
ports:
- port: 3000
name: api
selector:
app: ticket-app
spec.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ticket-openapi
namespace: apps
data:
openapi.yaml: |
openapi: "3.0.0"
info:
version: 1.0.0
title: Tickets
description: OpenAPI specification based on Swagger Petstore (https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore.yaml).
servers:
- url: https://api.traefik.localhost
paths:
/tickets:
get:
summary: Get tickets
operationId: getTickets
tags:
- tickets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
maximum: 100
format: int32
responses:
'200':
description: A paged array of tickets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Tickets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a ticket
operationId: createTicket
tags:
- tickets
responses:
'201':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/tickets/{ticketId}:
get:
summary: Info for a specific ticket
operationId: showTicketById
tags:
- tickets
parameters:
- name: ticketId
in: path
required: true
description: The id of the ticket
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Ticket"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
put:
summary: Update a ticket
operationId: updateTicket
tags:
- tickets
parameters:
- name: ticketId
in: path
required: true
description: The id of the ticket
schema:
type: string
responses:
'200':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
delete:
summary: Delete a ticket
operationId: deleteTicket
tags:
- tickets
parameters:
- name: ticketId
in: path
required: true
description: The id of the ticket
schema:
type: string
responses:
'200':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Ticket:
type: object
required:
- id
- flightCode
properties:
id:
type: integer
format: int64
flightCode:
type: string
fare:
type: integer
format: int64
class:
type: string
available:
type: integer
format: int64
total:
type: integer
format: int64
Tickets:
type: array
maxItems: 100
items:
$ref: "#/components/schemas/Ticket"
Error:
type: object
required:
- message
properties:
message:
type: string
The following kubectl
commands will deploy the API:
kubectl apply -f api.yaml \
-f ticket.yaml \
-f spec.yaml
5. Configure API access¶
In step five, you will configure the access permissions for the API Gateway.
For doing so, change back into the top level directory of this tutorial, hub-demo
and create a file called api-access.yaml
with the following content:
api-access.yaml
---
apiVersion: hub.traefik.io/v1alpha1
kind: APIAccess
metadata:
name: customer-admin
spec:
groups:
- ignored-atm
apiSelector:
matchLabels:
area: customers
---
apiVersion: hub.traefik.io/v1alpha1
kind: APIAccess
metadata:
name: crm-apis
spec:
groups:
- ignored-atm
apiSelector:
matchLabels:
module: crm
---
apiVersion: hub.traefik.io/v1alpha1
kind: APIAccess
metadata:
name: crm-collections
spec:
groups:
- ignored-atm
apiCollectionSelector:
matchLabels:
module: crm
---
apiVersion: hub.traefik.io/v1alpha1
kind: APIAccess
metadata:
name: custom-pick
spec:
groups:
- ignored-atm
apiSelector:
matchExpressions:
- key: area
operator: In
values:
- flights
- support
Use kubectl
to deploy it:
kubectl apply -f api-access.yaml
6. Configure the API Gateway¶
Now it is time to configure the Gateway for your APIs.
In Traefik Hub, an API Gateway is the main entry point to all your APIs.
This is where you define the public domains for your APIs and which APIs and API collections you want to expose via an APIAccess CRD.
For doing so, change back into the top level directory of this tutorial, hub-demo
and create a file called api-gateway.yaml
with the following content:
api-gateway.yaml
---
apiVersion: hub.traefik.io/v1alpha1
kind: APIGateway
metadata:
name: my-gateway
labels:
area: crm
spec:
apiAccesses:
- customer-admin
- crm-collections
- crm-apis
- custom-pick
Use kubectl
to deploy it:
kubectl apply -f api-gateway.yaml
6.1 Access an API via the Gateway¶
kubectl get apigateway -n apps
Follow the URL in the output plus the API prefix you want to reach, for example
7. Configure the API Portal¶
In Traefik Hub, the API Portal is the landing page of an API or an API collection.
In the Portal, the consumer can view a representation of the OpenAPI specification and effortlessly interact and try out every API operation.
For doing so, change back into the top level directory of this tutorial, hub-demo
and create a file called api-portal.yaml
with the following content:
api-portal.yaml
---
apiVersion: hub.traefik.io/v1alpha1
kind: APIPortal
metadata:
name: my-preview-portal
spec:
title: "Traefik Airlines"
description: "Traefik Airlines API Portal"
apiGateway: my-gateway
Use kubectl
to deploy it:
kubectl apply -f api-portal.yaml
7.1 Access the API Portal¶
kubectl get apiportal -n apps
Follow the URL in the output
8. Sending API requests¶
In the last part of this tutorial, you will use curl or HTTPIe to interact with the deployed Customers API.
curl¶
curl is s widely-used by developers for quickly testing REST APIs in the command line.
The following command will perform the request and output the response body:
curl -v --location https://parental-camel-vamdrm.yzxs6p9v.preview.traefikhub.dev/customers/customers
Which will show:
curl -v --location https://parental-camel-vamdrm.yzxs6p9v.preview.traefikhub.dev/customers/customers
* Trying 52.56.86.87:443...
* Connected to parental-camel-vamdrm.yzxs6p9v.preview.traefikhub.dev (52.56.86.87) port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
* CAfile: /etc/ssl/cert.pem
* CApath: none
* [CONN-0-0][CF-SSL] (304) (OUT), TLS handshake, Client hello (1):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, Server hello (2):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, Unknown (8):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, Certificate (11):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, CERT verify (15):
* [CONN-0-0][CF-SSL] (304) (IN), TLS handshake, Finished (20):
* [CONN-0-0][CF-SSL] (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
* ALPN: server accepted h2
* Server certificate:
* subject: CN=*.yzxs6p9v.preview.traefikhub.dev
* start date: Feb 28 11:52:59 2023 GMT
* expire date: May 29 11:52:58 2023 GMT
* subjectAltName: host "parental-camel-vamdrm.yzxs6p9v.preview.traefikhub.dev" matched cert's "*.yzxs6p9v.preview.traefikhub.dev"
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* h2h3 [:method: GET]
* h2h3 [:path: /customers/customers]
* h2h3 [:scheme: https]
* h2h3 [:authority: parental-camel-vamdrm.yzxs6p9v.preview.traefikhub.dev]
* h2h3 [user-agent: curl/7.87.0]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x12b010a00)
> GET /customers/customers HTTP/2
> Host: parental-camel-vamdrm.yzxs6p9v.preview.traefikhub.dev
> user-agent: curl/7.87.0
> accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 200
< access-control-allow-credentials: true
< cache-control: no-cache
< content-type: application/json; charset=utf-8
< date: Fri, 31 Mar 2023 13:04:11 GMT
< etag: W/"152-YYUUBmMg0FfHP0BwM9kbIO/ll84"
< expires: -1
< pragma: no-cache
< vary: Origin, Accept-Encoding
< x-content-type-options: nosniff
< x-powered-by: Express
< content-length: 338
<
[
{
"id": 1,
"firstName": "John",
"lastName": "Doe",
"points": 100,
"status": "bronze"
},
{
"id": 2,
"firstName": "Jane",
"lastName": "Doe",
"points": 200,
"status": "silver"
},
{
"id": 3,
"firstName": "John",
"lastName": "Smith",
"points": 300,
"status": "gold"
}
* Connection #0 to host parental-camel-vamdrm.yzxs6p9v.preview.traefikhub.dev left intact
]%
HTTPie¶
HTTPIe make it painless to test and debug APIs, HTTP servers, and web services.
In the following example, you will run a GET request against the /customers
endpoint of the example API.
https https://parental-camel-vamdrm.yzxs6p9v.preview.traefikhub.dev/customers/customers
This will create the following (colorized and formatted) output:
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Content-Length: 338
Content-Type: application/json; charset=utf-8
Date: Fri, 31 Mar 2023 13:14:12 GMT
Etag: W/"152-YYUUBmMg0FfHP0BwM9kbIO/ll84"
Expires: -1
Pragma: no-cache
Vary: Origin, Accept-Encoding
X-Content-Type-Options: nosniff
X-Powered-By: Express
[
{
"firstName": "John",
"id": 1,
"lastName": "Doe",
"points": 100,
"status": "bronze"
},
{
"firstName": "Jane",
"id": 2,
"lastName": "Doe",
"points": 200,
"status": "silver"
},
{
"firstName": "John",
"id": 3,
"lastName": "Smith",
"points": 300,
"status": "gold"
}
]
Summary¶
In this tutorial, you learned how to:
- Deploy APIs with CRDs
- Configures access and permissions of APIs and API collections
- Configure an API Gateway
- Expose an API Portal
- Use HTTPIe or curl for sending API requests
What's next¶
- Learn more about API management from CRDs