Response Validation
Plenum includes internal:validate-response, a built-in interceptor that validates upstream response bodies against the response schema defined in your OpenAPI spec for the matching status code.
Working example: see
examples/validation/
Configuration
Section titled “Configuration”Attach the interceptor to any operation that has a response schema:
actions: - target: "$.paths['/items'].post" update: x-plenum-interceptor: - module: "internal:validate-response" hook: "on_response_body" function: "validateResponse"The interceptor reads the schema from the spec’s responses.<status>.content.application/json.schema automatically, including $ref references to components/schemas.
Upstream configuration
Section titled “Upstream configuration”Response validation requires the full response body to be buffered before the interceptor can inspect it. This means buffer-response: true must be set on the upstream:
upstreams: - name: api url: https://api.example.com buffer-response: true # required for response validationThe gateway refuses to start at boot time if on_response_body interceptors are configured without buffer-response: true on the upstream.
For a detailed explanation of how body buffering works, body type representations, and performance considerations, see Body Buffering.
Behaviour
Section titled “Behaviour”When validation fails, the gateway returns an error response instead of forwarding the upstream response:
# Valid response — proxied to client$ curl -X POST http://localhost:6188/items \ -H "Content-Type: application/json" \ -d '{"name": "Widget", "quantity": 5}'# => 201 {"id": 1, "name": "Widget", "quantity": 5}
# Response missing required field — replaced with 502$ curl -X POST http://localhost:6188/items \ -H "Content-Type: application/json" \ -d '{"name": "Widget", "quantity": 5}'# => 502 {"error": "upstream response validation failed"}What gets validated
Section titled “What gets validated”The interceptor validates against the JSON Schema from the spec’s response definition for the actual status code returned by the upstream, including:
- Required fields
- Type checking (string, integer, boolean, etc.)
- Additional constraints (enum, pattern, min/max, etc.)
$refreferences to shared schemas incomponents/schemas
Overriding the schema
Section titled “Overriding the schema”To validate against a different schema, provide an explicit options.schema:
x-plenum-interceptor: - module: "internal:validate-response" hook: "on_response_body" function: "validateResponse" options: schema: type: object properties: id: type: integer name: type: string quantity: type: integer required: - id - name - quantityWhen options.schema is provided, it takes precedence over the spec schema across all status codes.
Body type considerations
Section titled “Body type considerations”The interceptor parses the response body according to the response Content-Type header. See Body Buffering for the full type mapping. Key points for response validation:
- JSON responses (
application/json): the body is parsed and validated as a JavaScript object - Malformed JSON: falls back to raw text without erroring — the validator can still inspect the status code and headers
- Binary responses: received as a base64-encoded string with
bodyEncoding: "base64". The validator checks the status and headers but skips body schema validation for non-JSON content types