express-openapi-validate
Express middleware to validate requests based on an OpenAPI 3.0 documentopenapi-3. OpenAPI specification was called the Swagger specification before version 3.
Usage
Install this package with npm or yarn:npm install --save express-openapi-validate
# or
yarn add express-openapi-validate
Then use the validator like this:
index.js
const fs = require("fs");
const express = require("express");
const { OpenApiValidator } = require("express-openapi-validate");
const jsYaml = require("js-yaml");
const app = express();
app.use(express.json());
const openApiDocument = jsYaml.safeLoad(
fs.readFileSync("openapi.yaml", "utf-8"),
);
const validator = new OpenApiValidator(openApiDocument);
app.post("/echo", validator.validate("post", "/echo"), (req, res, next) => {
res.json({ output: req.body.input });
});
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
res.status(statusCode).json({
error: {
name: err.name,
message: err.message,
data: err.data,
},
});
});
const server = app.listen(3000, () => {
console.log("Listening on", server.address());
});
Or using
match()
:// Apply to all requests
app.use(validator.match());
// On each request validator.validate("post", "/echo") is called automatically,
// if it has a matching specification in the OpenAPI schema
app.post("/echo", (req, res, next) => {
res.json({ output: req.body.input });
});
openapi.yaml
openapi: 3.0.1
info:
title: Example API with a single echo endpoint
version: 1.0.0
components:
schemas:
Error:
type: object
properties:
error:
type: object
properties:
name:
type: string
message:
type: string
data:
type: array
items:
type: object
required:
- name
- message
required:
- error
responses:
error:
description: Default error response with error object
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
paths:
/echo:
post:
description: Echo input back
requestBody:
content:
application/json:
schema:
type: object
properties:
input:
type: string
required:
- input
responses:
"200":
description: Echoed input
content:
application/json:
schema:
type: object
properties:
output:
type: string
default:
$ref: "#/components/responses/error"
Supported features
- Validating request bodies with a schema (See Request Body
[JSON Schema][json-schema] and [Ajv][ajv] are used in validation
- Schemas are validated according to JSON Schema Specification Wright Draft00][json-schema-validation-05] (draft-04/05) as specified in [OpenAPI
specification][openapi-data-types]
- nullable
field for handling properties that can be null is supported (See[OpenAPI fixed fields][openapi-fixed-fields])
- Validation according to format
including additional data type formats(like int32 and bytes) defined by OpenAPI (See [OpenAPI data
types][openapi-data-types] and [Ajv formats][ajv-formats])
- Validating parameters: query, header, path and cookies (including signed
schema
features that are supported for request bodies are alsosupported for parameters
- required
field for marking parameters that must be given is supported- Validating response bodies and headers in tests (See Responses
- References to Components Objectopenapi-components-object (See Reference
- Typescript definitions are included in the package
- Discriminator keyword
Currently unsupported features
- Validating request bodies with media type other than
application/json
(See
content
under Request Body Objectopenapi-request-body-object)
unsupported:
- deprecated
- xml
- External references (references to other files and network resources) (See
- Parameter Objectsopenapi-parameter-object (including Header
content
and style
(only schema
is supported)- Links and callbacks (See Callback Objectopenapi-callback-object and Link
- Encodings (See Encoding Objectopenapi-encoding-object)
Public API
class OpenApiValidator
const { OpenApiValidator } = require("express-openapi-validate");
The main class of this package. Creates JSON schemajson-schema validators for the given operations defined in the OpenAPI document. In the background Ajvajv is used to validate the request.
constructor(openApiDocument: OpenApiDocument, options: ValidatorConfig = {}))
Creates a new validator for the given OpenAPI document.options
parameter is optional. It has the following optional fields:{
ajvOptions: Ajv.Options;
}
You can find the list of options accepted by Ajv from its documentationajv-options. The
formats
object passed to Ajv will be merged
with additional OpenAPI formatsopenapi-formats supported by this library.validate(method: Operation, path: string): RequestHandler
Returns an express middleware function for the given operation. The operation
matching the given method and path has to be defined in the OpenAPI document or
this method throws.The middleware validates the incoming request according to the
parameters
and
requestBody
fields defined in the Operation
Objectopenapi-operation-object. If the validation fails the next
express
function is called with an
ValidationError
.See the Parameter Objectopenapi-parameter-object and Request Body Objectopenapi-request-body-object sections of the OpenAPI specification for details how to define schemas for operations.
method
must be one of the valid operations of an OpenAPI Path Item
Objectopenapi-path-item-object:
"get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace"
.RequestHandler
is an express middleware function with the signature
(req: Request, res: Response, next: NextFunction): any;
.match(options: MatchOptions = { allowNoMatch: false }): RequestHandler
Returns an express middleware function which calls validate()
based on the
request method and path. Using this function removes the need to specify
validate()
middleware for each express endpoint individually.match()
throws an error if matching route specification is not found. This
ensures all requests are validated.Use
match({ allowNoMatch: true})
if you want to skip validation for routes
that are not mentioned in the OpenAPI schema. Use with caution: It allows
requests to be handled without any validation.The following examples achieve the same result:
// Using validate()
app.post("/echo", validator.validate("post", "/echo"), (req, res, next) => {
res.json({ output: req.body.input });
});
// Using match()
app.use(validator.match());
app.post("/echo", (req, res, next) => {
res.json({ output: req.body.input });
});
validateResponse(method: Operation, path: string): (res: any) => void
Creates a function for the given operation that can be used to validate
responses. Response validation is meant to be used in tests and not in
production code. See below for example usage.For documentation of the
method
and path
parameters see
validate
.res
is expected to have the shape
{ statusCode: number, body: {}, headers: {}}
. The statusCode
field can also
be called status
and the body
field can be called data
. This means that
response objects from most request libraries should work out of the box.If validation fails the validation function throws a
ValidationError
. Otherwise it returns
undefined
.Example usage when using Jestjest and SuperTestsupertest:
import { OpenApiValidator } from "express-openapi-validate";
import fs from "fs";
import jsYaml from "js-yaml";
import request from "supertest";
import app from "./app";
const openApiDocument = jsYaml.safeLoad(
fs.readFileSync("openapi.yaml", "utf-8"),
);
const validator = new OpenApiValidator(openApiDocument);
test("/echo responses", async () => {
const validateResponse = validator.validateResponse("post", "/echo");
let res = await request(app).post("/echo").send({});
expect(validateResponse(res)).toBeUndefined();
res = await request(app).post("/echo").send({ input: "Hello!" });
expect(validateResponse(res)).toBeUndefined();
});
class ValidationError extends Error
const { ValidationError } = require("express-openapi-validate");
This error is thrown by
OpenApiValidator#validate
when the request validation
fails. It contains useful information about why the validation failed in
human-readable format in the .message
field and in machine-readable format in
the .data
array.You can catch this error in your express error handler and handle it specially. You probably want to log the validation error and pass the errors to the client.
message: string
Human-readable error message about why the validation failed.statusCode: number = 400
This field is always set to 400
. You can check this field in your express
error handler to decide what status code to send to the client when errors
happen.data: ErrorObject[]
Machine-readable array of validation errors. Ajv Error
Objectsajv-error-objects documentation contains a list of the fields in
ErrorObject
.