Validate requests before they reach their upstream Service. Supports request body validation, according to a schema. Note: the schema format is NOT JSON schema compliant; instead, Kong’s own schema format is used.
Terminology
plugin
: a plugin executing actions inside Kong before or after a request has been proxied to the upstream API.Service
: the Kong entity representing an external upstream API or microservice.Route
: the Kong entity representing a way to map downstream requests to upstream services.Consumer
: the Kong entity representing a developer or machine using the API. When using Kong, a Consumer only communicates with Kong which proxies every call to the said upstream API.Credential
: a unique string associated with a Consumer, also referred to as an API key.upstream service
: this refers to your own API/service sitting behind Kong, to which client requests are forwarded.
Configuration
Enabling the plugin on a Service
With a database
Configure this plugin on a Service by making the following request:
$ curl -X POST http://kong:8001/services/{service}/plugins \
--data "name=request-validator" \
--data "config.body_schema=[{"name":{"type": "string", "required": true}}]" \
--data "config.version=kong"
Without a database
Configure this plugin on a Service by adding this section do your declarative configuration file:
plugins:
- name: request-validator
service: {service}
config:
body_schema: [{"name":{"type": "string", "required": true}}]
version: kong
In both cases, {service}
is the id
or name
of the Service that this plugin configuration will target.
Enabling the plugin on a Route
With a database
Configure this plugin on a Route with:
$ curl -X POST http://kong:8001/routes/{route}/plugins \
--data "name=request-validator" \
--data "config.body_schema=[{"name":{"type": "string", "required": true}}]" \
--data "config.version=kong"
Without a database
Configure this plugin on a Route by adding this section do your declarative configuration file:
plugins:
- name: request-validator
route: {route}
config:
body_schema: [{"name":{"type": "string", "required": true}}]
version: kong
In both cases, {route}
is the id
or name
of the Route that this plugin configuration will target.
Enabling the plugin on a Consumer
With a database
You can use the http://localhost:8001/plugins
endpoint to enable this plugin
on specific Consumers:
$ curl -X POST http://kong:8001/consumers/{consumer}/plugins \
--data "name=request-validator" \
\
--data "config.body_schema=[{"name":{"type": "string", "required": true}}]" \
--data "config.version=kong"
Without a database
Configure this plugin on a Consumer by adding this section do your declarative configuration file:
plugins:
- name: request-validator
consumer: {consumer}
config:
body_schema: [{"name":{"type": "string", "required": true}}]
version: kong
In both cases, {consumer}
is the id
or username
of the Consumer that this plugin configuration will target.
You can combine consumer_id
and
service_id
in the same request, to furthermore narrow the scope of the plugin.
Global plugins
- Using a database, all plugins can be configured using the
http://kong:8001/plugins/
endpoint. - Without a database, all plugins can be configured via the
plugins:
entry on the declarative configuration file.
A plugin which is not associated to any Service, Route or Consumer (or API, if you are using an older version of Kong) is considered "global", and will be run on every request. Read the Plugin Reference and the Plugin Precedence sections for more information.
Parameters
Here's a list of all the parameters which can be used in this plugin's configuration:
form parameter | description |
---|---|
name | The name of the plugin to use, in this case request-validator |
service.id | The id of the Service which this plugin will target. |
route.id | The id of the Route which this plugin will target. |
enabled default value: true | Whether this plugin will be applied. |
config.body_schema
|
Array of schema fields |
config.allowed_content_types
optional default value: {“application/json”=>nil} |
Set of allowed content types |
config.version
default value: kong |
validator type |
config.parameter_schema
optional |
Array of parameter validator specification |
Examples
Overview
By applying the plugin to a Service, all requests to that Service will be validated before being proxied.
With a database
Use a request like this:
curl -i -X POST http://kong:8001/services/{service}/plugins \
--data "name=request-validator" \
--data 'config.body_schema=[{"name":{"type": "string", "required": true}}]'
Without a database
Add the following entry to the plugins:
section in the declarative configuration file:
plugins:
- name: request-validator
service: {service}
config:
body_schema:
name:
type: string
required: true
The parameters/fields in both cases mean:
form parameter | description |
---|---|
{service} |
The id or name of the Service to which the plugin will be associated. |
name |
The name of the plugin to use, in this case: request-validator |
config.body_schema |
The request body schema specification |
In this example, the request body data would have to be a valid JSON and
conform to the schema specified in body_schema
- i.e., it would be required
to contain a name
field only, which needs to be a string.
Schema Definition
The config.body_schema
field expects a JSON array with the definition of each
field expected to be in the request body; for example:
Each field definition contains the following attributes:
Attribute | Required | Description |
---|---|---|
type |
yes | The expected type for the field |
required |
no | Whether or not the field is required |
Additionally, specific types may have their own required fields:
Map:
Attribute | Required | Description |
---|---|---|
keys |
yes | The schema for the map keys |
values |
yes | The schema for the map values |
Example string-boolean map:
{
"type": "map",
"keys": {
"type": "string"
},
"values": {
"type": "boolean"
}
}
Array:
Attribute | Required | Description |
---|---|---|
elements |
yes | The array’s elements schema |
Example integer array schema:
{
"type": "array",
"elements": {
"type": "integer"
}
}
Record:
Attribute | Required | Description |
---|---|---|
fields |
yes | The record schema |
Example record schema:
{
"type": "record",
"fields": [
{
"street": {
"type": "string",
}
},
{
"zipcode": {
"type": "string",
}
}
]
}
The type
field assumes one the following values:
string
number
integer
boolean
map
array
record
Each field specification may also contain “validators”, which perform specific validations:
Validator | Applies to | Description |
---|---|---|
between |
Integers | Whether the value is between two integer. Specified as an array; e.g., {1, 10} |
len_eq |
Arrays, Maps, Strings | Whether an array’s length is a given value |
len_min |
Arrays, Maps, Strings | Whether an array’s length is at least a given value |
len_max |
Arrays, Maps, strings | Whether an array’s length is at most a given value |
match |
Strings | True if the value matches a given Lua pattern ** |
not_match |
String | True if the value doesn’t match a given Lua pattern ** |
match_all |
Arrays | True if all strings in the array match the specified Lua pattern ** |
match_none |
Arrays | True if none of the strings in the array match the specified Lua pattern ** |
match_any |
Arrays | True if any one of the strings in the array matches the specified Lua pattern ** |
starts_with |
Strings | True if the string value starts with the specified substring |
one_of |
Strings, Numbers, Integers | True if the string field value matches one of the specified values |
timestamp |
Integers | True if the field value is a valid timestamp |
uuid |
Strings | True if the string is a valud UUID |
Note: check this out to learn about Lua patterns.
Schema Example
[
{
"name": {
"type": "string",
"required": true
}
},
{
"age": {
"type": "integer",
"required": true
}
},
{
"address": {
"type": "record",
"required": true,
"fields": [
{
"street": {
"type": "string",
"required": true
}
},
{
"zipcode": {
"type": "string",
"required": true
}
}
]
}
}
]
Such a schema would validate the following request body:
{
"name": "Gruce The Great",
"age": 4,
"address": {
"street": "251 Post St.",
"zipcode": "94108"
}
}
In case either the JSON or schema validation fail, a 400 Bad Request
will
be returned as response.
Parameter Schema Definition
You can setup definitions for each parameter based of the OpenAPI Specification and the plugin will validate each parameter against it. For more information see the OpenAPI spec or the OpenAPI examples.
Fixed Fields
Field Name | Type | Description |
---|---|---|
name | string |
REQUIRED. The name of the parameter. Parameter names are case sensitive, and corresponds to the parameter name used by the in property. If in is "path" , the name field MUST correspond to the named capture group from the configured route . |
in | string |
REQUIRED. The location of the parameter. Possible values are “query”, “header” or “path”. |
required | boolean |
REQUIRED Determines whether this parameter is mandatory. |
style | string |
REQUIRED when schema and explode are set Describes how the parameter value will be serialized depending on the type of the parameter value. |
schema | string |
REQUIRED when style and explode are set The schema defining the type used for the parameter. It is validated using draft4 for JSONschema draft 4 compliant validator. |
explode | boolean |
REQUIRED when schema and style are set When this is true, parameter values of type array or object generate separate parameters for each value of the array or key-value pair of the map. For other types of parameters this property has no effect. |
Examples
In this example we will use the plugin to validate a request’s path parameter.
-
Add a service to Kong
curl -i -X POST http://kong:8001/services \ --data name=httpbin \ --data url=http://httpbin.org HTTP/1.1 201 Created .. { "host":"httpbin.org", "created_at":1563479714, "connect_timeout":60000, "id":"0a7f3795-bc92-43b5-aada-258113b7c4ed", "protocol":"http", "name":"httpbin", "read_timeout":60000, "port":80, "path":null, "updated_at":1563479714, "retries":5, "write_timeout":60000 }
-
Add a route with named capture group
curl -i -X POST http://kong:8001/services/httpbin/routes \ --data paths="/status/(?<status_code>\d%+)" \ --data strip_path=false HTTP/1.1 201 Created .. { "created_at": 1563481399, "methods": null, "id": "cd78749a-33a3-4bbd-9560-588eaf4116d3", "service": { "id": "0a7f3795-bc92-43b5-aada-258113b7c4ed" }, "name": null, "hosts": null, "updated_at": 1563481399, "preserve_host": false, "regex_priority": 0, "paths": [ "\\/status\\/(?<status_code>\\d+)" ], "sources": null, "destinations": null, "snis": null, "protocols": [ "http", "https" ], "strip_path": false }
-
Enable request-validator plugin to validate body and parameter
curl -i -X POST http://kong:8001/services/httpbin/plugins \ --header "Content-Type: application/json" \ --data @parameter_schema.json HTTP/1.1 201 Created .. { "created_at": 1563483059, "config": { "body_schema": "{\"name\":{\"type\": \"string\", \"required\": false}}", "parameter_schema": [ { "style": "simple", "required": true, "in": "path", "schema": "{\"type\": \"number\"}", "explode": false, "name": "status_code" } ], "version": "draft4" }, "id": "ad91a2d4-6217-4d34-9133-4a2508ddda9f", "service": { "id": "0a7f3795-bc92-43b5-aada-258113b7c4ed" }, "enabled": true, "run_on": "first", "consumer": null, "route": null, "name": "request-validator" }
content of file
parameter_schema.json
{ "name": "request-validator", "config": { "body_schema": "{\"name\":{\"type\": \"string\", \"required\": false}}", "version": "draft4", "parameter_schema": [ { "name": "status_code", "in": "path", "required": true, "schema": "{\"type\": \"number\"}", "style": "simple", "explode": false } ] } }
Here validation will make sure
status_code
is a number. -
A proxy request with a non-numerical status code will be blocked
curl -i -X GET http://kong:8000/status/abc HTTP/1.1 400 Bad Request .. {"message":"request param doesn't conform to schema"}
but it will be allowed with a numeric status code
curl -i -X GET http://kong:8000/status/200 HTTP/1.1 200 OK X-Kong-Upstream-Latency: 163 X-Kong-Proxy-Latency: 37 ..
Further References
Check out the Kong docs on storing custom entities here.