Skip to main content

request-validation

Validates request headers and body against a JSON Schema.

Category TrafficAdd it to Route, Service, Consumer, Consumer group, Global rule, Plugin configEngine plugin request-validationPriority 2800

What it does​

request-validation reads each request on the route against a JSON Schema before it is passed on: the body against Body schema, the headers against Header schema. A request that does not match is answered with Rejected code, 400 unless you change it, and does not reach the backend.

A body that passes does not reach the backend byte for byte. The backend gets the parsed JSON written out again, with keys reordered and spacing and number formatting changed.

When to use it​

  • An orders API whose backend must only see orders with a positive amount and a currency it handles.
  • A route that partners call with a tenant header the backend needs, x-tenant for example, where a call without it stops at the gateway.
  • A backend that fails on malformed input, kept behind a check that answers the client with a clear message of your own instead.
  • Large uploads that must stop at the gateway, capped under Request body limit.

Not for checking requests against a whole OpenAPI document — see oas-validator (Validates requests against an OpenAPI document; responses are not checked) or changing the body before it reaches the backend — see body-transformer (Rewrites request and response bodies with templates).

Guides​

Pages that walk through a job with request-validation, step by step.

Set it up​

Refuse an order without a positive amount and a known currency​

Fill Body schema as in the JSON below, set Rejected code to 422 and set Rejected message to The order body was not understood..

The console's Add plugin panel, filled with this example.
request-validation · as the console saves it
{
"body_schema": {
"type": "object",
"required": [
"amount",
"currency"
],
"properties": {
"amount": {
"type": "integer",
"minimum": 1
},
"currency": {
"type": "string",
"enum": [
"EUR",
"USD"
]
}
}
},
"rejected_code": 422,
"rejected_msg": "The order body was not understood."
}

What you will see​

  • An order whose amount is 0 is answered 422 with The order body was not understood.; the backend never sees it.
  • An order in a currency the schema does not list, GBP, is answered 422 with the same message.
  • An order with a positive amount in euros is passed on and answered 200 by the backend.
  • A GET without a body on a route that carries this plugin is answered 422 too, so the plugin belongs on the route that takes the writes and not on the one that answers reads.

Things to know​

  • Body schema — In the example, an order whose amount is 0, or whose currency is GBP, is answered 422 with the Rejected message. One with an amount of 5 in EUR passes and is answered 200.
  • Body schema — A body that passes is re-encoded from what was read: the upstream gets the parsed JSON, not the bytes the client sent.
  • Header schema — A header reaches the schema as text, so a property typed as a number never matches, and a header sent twice arrives as a list.
  • Rejected code — A 2xx status is stored too, and the request is still not passed on.
  • Rejected code — A status below 200, 199 for example, is refused when you save.
  • Rejected message — Left empty, the client is answered with the validator's own sentence, which names the properties the schemas above carry.
  • A configuration with neither Body schema nor Header schema is refused when you save.
  • AdviceStart from a schema the backend's own tests already use, so the gateway and the backend refuse the same bodies.

Settings​

The fields as the console shows them, section by section.

Body schemabody_schemaobjectRequired unless Header schema is set

A JSON Schema the request body must match, such as {"type": "object", "required": ["name"]}. A body that passes is re-encoded from what was read: the upstream gets the parsed JSON, with keys reordered and spacing and number formatting changed, not the bytes the client sent.

example {"type":"object","required":["amount"],"properties":{"amount":{"type":"integer","minimum":1}}}
Header schemaheader_schemaobjectRequired unless Body schema is set

A JSON Schema the request's headers are read against before it is passed on.

example {"type":"object","required":["x-tenant"],"properties":{"x-tenant":{"type":"string","minLength":3}}}
Rejected coderejected_codeintegerdefault 400

The status a refused request is answered with. A 2xx status is stored too, and the request is still not passed on.

200 to 599
Rejected messagerejected_msgstring

Sent to the client as the whole body of the refusal.

1 to 256 characters
Request body limitmax_req_body_sizeintegerdefault 67108864

Bytes of the request body read into memory before the body schema is applied; a longer body is refused with the Rejected code.

at least 1

Every plugin also has Enabled, Priority, Filter, Error response and Pre-function: see Plugin execution settings.

G8 dev · Apache APISIX® 3.19.0
Apache, Apache APISIX and APISIX are trademarks of The Apache Software Foundation.
Facts
Category
Traffic
Add it to
Route, Service, Consumer, Consumer group, Global rule, Plugin config
Engine plugin
request-validation
Priority
2800