Skip to main content

Schema and Handler

Updated Feb 26, 2023 ·

Overview

Custom plugins in Kong allow you to extend Kong’s functionality by adding tailored logic for specific use cases. These plugins integrate seamlessly into the Kong API Gateway and can handle requests, responses, and transformations.

  • Custom plugins enhance API management.
  • They allow precise control over API workflows.

To create custom plugins, it is recommended to learn the Lua programming language, as Kong plugins are primarily written in Lua.

For more information, please see Develop Custom Plugins.

Lab Environment

This lab deploys Kong API Gateway and other applications in a Windows 10 machine using a docker compose file.

info

Make sure that you have installed Docker Desktop.

Simply installing Docker in WSL2 without Docker Desktop may introduce some issue when configuring the communication between the containerized Kong API Gateway and the FastAPI application that is installed on the local host.

Pre-requisites

Configure the Service and Route

Run the command below to create the request-service:

curl -X POST http://localhost:8001/services \
-H "Content-Type: application/json" \
-d '{
"name": "request-service",
"protocol": "http",
"host": "host.docker.internal",
"port": 5000,
"path": "/healthy"
}'

Next, create the request-route:

curl -X POST http://localhost:8001/routes \
-H "Content-Type: application/json" \
-d '{
"name": "request-route",
"methods": ["GET", "POST"],
"paths": ["/prod"],
"service": {
"name": "request-service"
}
}'

Open a web browser and access the Kong Manager UI:

http://localhost:8002/ 

Verify that the service and route are created.

Back on the terminal run the command below. It should return a healthy status.

$ curl --location 'http://localhost:8000/prod'

{"status":"Healthy"}
info

To make this work, make sure the FastAPI Endpoint is set up on your local machine.

Create the Custom Plugin

In this example, we will create a plugin named check_header, which verifies if a specific header exists in incoming API requests. Create the necessary folder and files:

$ ls -la check_header/

total 2
drwxrwxrwx 1 johnsmith johnsmith 512 Dec 7 18:52 .
drwxrwxrwx 1 johnsmith johnsmith 512 Dec 7 19:05 ..
-rwxrwxrwx 1 johnsmith johnsmith 506 Nov 19 02:29 handler.lua
-rwxrwxrwx 1 johnsmith johnsmith 602 Nov 19 02:29 schema.lua

The schema.lua file defines the parameters that users will provide.

local typedefs = require "kong.db.schema.typedefs"


local PLUGIN_NAME = "check_header"


local schema = {
name = PLUGIN_NAME,
fields = {
{ consumer = typedefs.no_consumer },
{ protocols = typedefs.protocols_http },
{ config = {
type = "record",
fields = {
{ request_header = typedefs.header_name {
required = true,
default = "accesstoken" } }
},
entity_checks = {
{ at_least_one_of = { "request_header" }, },
{ distinct = { "request_header"} },
},
},
},
},
}

return schema

The handler.lua file contains the logic for processing API requests.

local plugin = {
PRIORITY = 1000,
VERSION = "0.1",
}

function plugin:init_worker()

kong.log.debug("Check Header Plugin: init_worker")

end


function plugin:access(plugin_conf)
kong.log.inspect(plugin_conf)
local headers = kong.request.get_headers()[plugin_conf.request_header]
if headers == nil then
kong.response.exit(403, { message = "No " .. tostring(plugin_conf.request_header) .." header found in the request" })
end
end


return plugin

Finally, create the kong.conf:

plugins = bundled, check_header
log_level = debug

Deploy the Custom Plugin

First, verify the container names.

$ docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}" 

CONTAINER ID IMAGE STATUS NAMES
e49b5348f0a0 pantsel/konga Up 59 seconds konga_web
c12e11fe189b dpage/pgadmin4:latest Up 59 seconds pgadmin
afc9c93a904f kong:3.7.1 Exited (0) 52 seconds ago kong-migrations-up
912503b7f7b2 kong:3.7.1 Exited (0) 52 seconds ago kong-migrations
bfb66d2826d7 logstash:8.11.3 Up 18 seconds logstash
e342e92d006d prom/prometheus:latest Up About a minute prometheus
ffa0ba3405eb postgres:16-alpine Up About a minute (healthy) konga-database
8105d9fdbeff elasticsearch:8.11.3 Up About a minute elasticsearch
b23d39ef273e kong:3.7.1 Up About a minute (healthy) kong-gateway
83d545085ec0 kibana:8.11.3 Up About a minute kibana
bd31a989f7b5 ealen/echo-server Up About a minute echo-server
63960d29315e grafana/grafana:latest Up About a minute grafana
17c48a410159 openzipkin/zipkin:latest Up About a minute (healthy) zipkin

Copy the plugin folder ("check_header") to Kong’s container in docker via the below command.

docker cp /path/to/check_header kong-gateway:/usr/local/share/lua/5.1/kong/plugins

Next, copy the kong.conf to the Kong container as well.

docker cp /path/to/kong.conf kong-gateway:/etc/kong/kong.conf 

Restart the container:

docker restart kong-gateway 

Run the Custom Plugin

Login to the Kong Manager UI > Plugins > Scroll to the bottom.

Click the plugin. On the Request Header field, specify any header name. This will be the header that the plugin will look for in every API request. Click Save.

Back on the terminal, run the command below. It should now fail.

$ curl --location 'http://localhost:8000/prod'

{"message":"No randomtoken header found in the request"}

Now add the required token. It should now succeed.

$ curl --location 'http://localhost:8000/prod' \
> -H "randomtoken: justputanytoken"

{"status":"Healthy"}