What is express-openapi-validator?
express-openapi-validator is a middleware for Express.js that validates API requests and responses against an OpenAPI 3.0 specification. It helps ensure that your API adheres to the defined contract, improving reliability and maintainability.
What are express-openapi-validator's main functionalities?
Request Validation
This feature validates incoming requests against the OpenAPI specification. If a request does not conform to the spec, an error is returned.
const express = require('express');
const OpenApiValidator = require('express-openapi-validator');
const app = express();
app.use(express.json());
app.use(
OpenApiValidator.middleware({
apiSpec: './api.yaml',
validateRequests: true,
})
);
app.post('/pets', (req, res) => {
res.json({ message: 'Pet added successfully' });
});
app.use((err, req, res, next) => {
res.status(err.status || 500).json({ message: err.message });
});
app.listen(3000, () => console.log('Server running on port 3000'));
Response Validation
This feature validates outgoing responses against the OpenAPI specification. If a response does not conform to the spec, an error is returned.
const express = require('express');
const OpenApiValidator = require('express-openapi-validator');
const app = express();
app.use(express.json());
app.use(
OpenApiValidator.middleware({
apiSpec: './api.yaml',
validateResponses: true,
})
);
app.get('/pets', (req, res) => {
res.json([{ id: 1, name: 'Fluffy' }]);
});
app.use((err, req, res, next) => {
res.status(err.status || 500).json({ message: err.message });
});
app.listen(3000, () => console.log('Server running on port 3000'));
Security Validation
This feature validates security requirements defined in the OpenAPI specification. It ensures that requests meet the necessary security criteria, such as API keys or OAuth tokens.
const express = require('express');
const OpenApiValidator = require('express-openapi-validator');
const app = express();
app.use(express.json());
app.use(
OpenApiValidator.middleware({
apiSpec: './api.yaml',
validateSecurity: true,
})
);
app.get('/secure-endpoint', (req, res) => {
res.json({ message: 'Secure data' });
});
app.use((err, req, res, next) => {
res.status(err.status || 500).json({ message: err.message });
});
app.listen(3000, () => console.log('Server running on port 3000'));
Other packages similar to express-openapi-validator
swagger-express-middleware
swagger-express-middleware is a similar package that provides middleware for Express.js to handle Swagger (OpenAPI) documents. It offers request validation, mock responses, and more. Compared to express-openapi-validator, it is more focused on Swagger 2.0 and provides additional features like mock responses.
openapi-backend
openapi-backend is a framework-agnostic library for building and validating APIs based on OpenAPI specifications. It provides request validation, response validation, and routing. Unlike express-openapi-validator, it is not tied to Express.js and can be used with other frameworks or even standalone.
ajv
ajv (Another JSON Schema Validator) is a JSON schema validator that can be used to validate data against JSON schemas, including OpenAPI schemas. While it is not specifically designed for Express.js or OpenAPI, it can be integrated into an Express.js application for similar validation purposes. It offers high performance and extensive features for JSON schema validation.
express-openapi-validator
An OpenApi validator for ExpressJS that automatically validates API requests using an OpenAPI 3 specification.
express-openapi-validator is unopinionated and does not impose any coding convention or project structure. Simply, install the validator onto your express app, point it to your OpenAPI 3 specification, then define and implement routes the way you prefer. See an example.
Install
npm i express-openapi-validator
Usage
Install the openapi validator
new OpenApiValidator({
apiSpecPath: './openapi.yaml',
}).install(app);
Then, register an error handler to customize errors
app.use((err, req, res, next) => {
res.status(err.status).json({
errors: err.errors,
});
});
Example Express API Server
Try the complete example below:
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var logger = require('morgan');
var http = require('http');
var app = express();
var OpenApiValidator = require('express-openapi-validator').OpenApiValidator;
app.use(bodyParser.json());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
const spec = path.join(__dirname, 'openapi.yaml');
app.use('/spec', express.static(spec));
new OpenApiValidator({
apiSpecPath: './openapi.yaml',
}).install(app);
app.get('/v1/pets', function(req, res, next) {
res.json([{ id: 1, name: 'max' }, { id: 2, name: 'mini' }]);
});
app.post('/v1/pets', function(req, res, next) {
res.json({ name: 'sparky' });
});
app.get('/v1/pets/:id', function(req, res, next) {
res.json({ id: req.params.id, name: 'sparky' });
});
app.post('/v1/pets/:id/photos', function(req, res, next) {
console.log(req.files);
res.json({
files_metadata: req.files.map(f => ({
originalname: f.originalname,
encoding: f.encoding,
mimetype: f.mimetype,
})),
});
});
app.use((err, req, res, next) => {
res.status(err.status).json({
errors: err.errors,
});
});
A fully working example lives here
Example validation responses
Validate a query parameter with a value constraint
/pets/:id
should be of type integer, express-openapi-validator returns:
curl http://localhost:3000/v1/pets/as |jq
{
"errors": [
{
"path": "id",
"errorCode": "type.openapi.validation",
"message": "should be integer",
"location": "path"
}
]
}
Validate a query parameter with a range constraint
/pets?limit=?
should be of type integer with a value greater than 5. It should also require an additional query paramter, test
, express-openapi-validator returns:
curl http://localhost:3000/v1/pets?limit=1 |jq
{
"errors": [
{
"path": "limit",
"errorCode": "minimum.openapi.validation",
"message": "should be >= 5",
"location": "query"
},
{
"path": "test",
"errorCode": "required.openapi.validation",
"message": "should have required property 'test'",
"location": "query"
}
]
}
Validate the query parameter's value type
POST /pets
is defined to only accept media type application/json, express-openapi-validator returns:
curl --request POST \
--url http://localhost:3000/v1/pets \
--header 'content-type: application/xml' \
--data '{
"name": "test"
}' |jq
{
"errors": [
{
"message": "Unsupported Content-Type application/xml"
}
]
}
Validate a POST body to ensure required parameters are present
POST /pets
request body is required to contain the name
properly, express-openapi-validator returns:
λ my-test curl --request POST \
--url http://localhost:3000/v1/pets \
--header 'content-type: application/json' \
--data '{
}'|jq
"errors": [
{
"path": "name",
"errorCode": "required.openapi.validation",
"message": "should have required property 'name'",
"location": "body"
}
]
}
Validate a POST multipart/form-data request
curl -XPOST http://localhost:3000/v1/pets/10/photos -F filez=@app.js | jq
{
"errors": [
{
"path": "file",
"errorCode": "required.openapi.validation",
"message": "should have required property 'file'",
"location": "body"
}
]
}
...and much more. Try it out!
License
MIT