Skip to content

validate-response

The internal:validate-response interceptor validates upstream response bodies against JSON Schemas. It resolves schemas from your OpenAPI spec’s responses definitions automatically, or from explicit options.schemas.

actions:
- target: "$.paths['/items'].post"
update:
x-plenum-interceptor:
- module: "internal:validate-response"
hook: on_response_body
function: validateResponse

Response validation requires buffer-response: true on the upstream. The gateway refuses to start at boot time if on_response_body interceptors are configured without it.

upstreams:
- name: api
url: https://api.example.com
buffer-response: true

See Body Buffering for details.

HookFunctionCan short-circuit
on_response_bodyvalidateResponseNo

The on_response_body hook is required — it’s the only hook with access to the full response body.

FieldTypeDefaultDescription
schemasRecord<string, object>Status code → JSON Schema map. If not set, reads from the operation’s responses.

When options.schemas is provided, it takes precedence. Keys are string status codes (e.g. "200", "404") or "default".

If no options.schemas is given, the interceptor walks the operation’s responses object and extracts schemas from each status code’s content.application/json.schema.

At request time, it looks up schemas[String(response.status)]. If no exact match, it falls back to schemas["default"]. If neither exists, validation is skipped.

  • Skips validation if the response body is null, undefined, or an empty string.
  • Parses string bodies as JSON. If parsing fails, returns 502 without error details (upstream returned malformed JSON).
  • Uses AJV with draft-07 support. Strict mode is off (strict: false).
  • Validators are cached per schema for performance.
  • Does not short-circuit — uses action: "continue" in all cases.

On validation failure, returns 502 with a simple error body:

{
"type": "response-validation-error",
"title": "Response Validation Failed",
"status": 502
}

Unlike validate-request, the response validator does not include per-field error details. It signals that the upstream response did not match the contract.

actions:
- target: "$.paths['/users/{id}'].get"
update:
x-plenum-interceptor:
- module: "internal:validate-response"
hook: on_response_body
function: validateResponse

With an explicit schema override:

x-plenum-interceptor:
- module: "internal:validate-response"
hook: on_response_body
function: validateResponse
options:
schemas:
"200":
type: object
properties:
id:
type: integer
name:
type: string
required:
- id
- name