OpenAPI Backend
Build, Validate, Route, and Mock using OpenAPI specification. Framework-agnostic middleware tools for building APIs with the OpenAPI standard.
OpenAPI Backend sits nicely in between your framework and business logic. It handles routing, input validation and response mocking; using only standard OpenAPI specification.
Also see: openapi-frontend
Features
- Build APIs by describing them in OpenAPI document specification and importing them via YAML or JSON files or just passing an object
- Register handler functions for operationIds to route requests in your favourite Node.js backend
- Use JSON Schema to validate API requests. OpenAPI Backend uses the AJV library under the hood for performant validation
- Mock API responses using OpenAPI examples objects or JSON Schema definitions
- TypeScript types included
(Currently only OpenAPI v3.0.0+ is supported)
Documentation
See DOCS.md
Quick Start
Full example projects included in the repo
npm install --save openapi-backend
import OpenAPIBackend from 'openapi-backend';
const api = new OpenAPIBackend({
definition: {
openapi: '3.0.1',
info: {
title: 'My API',
version: '1.0.0',
},
paths: {
'/pets': {
get: {
operationId: 'getPets',
responses: {
200: { description: 'ok' },
},
},
},
'/pets/{id}': {
get: {
operationId: 'getPetById',
responses: {
200: { description: 'ok' },
},
},
parameters: [
{
name: 'id',
in: 'path',
required: true,
schema: {
type: 'integer',
},
},
],
},
},
},
handlers: {
// your platform specific request handlers here
getPets: (c, req, res) => res.status(200).json({ result: 'ok' }),
getPetById: (c, req, res) => res.status(200).json({ result: 'ok' }),
validationFail: (c, req, res) => res.status(400).json({ err: c.validation.errors }),
notFound: (c, req, res) => res.status(404).json({ err: 'not found' }),
},
});
// initalize the backend
api.init();
Express
import express from 'express';
const app = express();
app.use(express.json());
app.use((req, res) => api.handleRequest(req, req, res));
app.listen(9000);
AWS Serverless (Lambda)
// API Gateway Proxy handler
module.exports.handler = (event, context) =>
api.handleRequest(
{
method: event.httpMethod,
path: event.path,
query: event.queryStringParameters,
body: event.body,
headers: event.headers,
},
event,
context,
);
See full Serverless Lambda example
Azure Function
module.exports = (context, req) =>
api.handleRequest(
{
method: req.method,
path: req.params.path,
query: req.query,
body: req.body,
headers: req.headers,
},
context,
req,
);
See full Azure Function example
Hapi
import Hapi from 'hapi';
const server = new Hapi.Server({ host: '0.0.0.0', port: 9000 });
server.route({
method: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
path: '/{path*}',
handler: (req, h) =>
api.handleRequest(
{
method: req.method,
path: req.path,
body: req.payload,
query: req.query,
headers: req.headers,
},
req,
h,
),
});
server.start();
Koa
import Koa from 'koa';
const app = new Koa();
app.use((ctx) =>
api.handleRequest(
{
method: ctx.request.method,
path: ctx.request.path,
body: ctx.request.body,
query: ctx.request.query,
headers: ctx.request.headers,
},
ctx,
),
);
app.listen(9000);
Registering Handlers for Operations
Handlers are registered for operationId
s found in the OpenAPI definitions. You can register handlers as shown above
with new OpenAPIBackend()
constructor opts, or using the register()
method.
async function getPetByIdHandler(c, req, res) {
const id = c.request.params.id;
const pet = await pets.getPetById(id);
return res.status(200).json({ result: pet });
}
api.register('getPetById', getPetByIdHandler);
Operation handlers are passed a special Context object as the first argument, which contains the parsed request, the matched API operation and input validation results. The other arguments in the example aboce are Express-specific handler arguments.
Request validation
You can enable request validation in your API by registering a validationFail
handler.
function validationFailHandler(c, req, res) {
return res.status(400).json({ status: 400, err: c.validation.errors });
}
api.registerHandler('validationFail', validationFailHandler);
This handler gets called if any JSON Schemas in either operation parameters (in: path, query, header, cookie) or requestPayload don't match the request.
The context object c
gets a validation
property with the validation result.
Mocking API responses
Mocking APIs just got really easy with OpenAPI Backend! Register a notImplemented
handler and use mockResponseForOperation()
to generate mock responses for operations with no custom handlers specified yet:
api.register('notImplemented', (c, req, res) => {
const { status, mock } = api.mockResponseForOperation(c.operation.operationId);
return res.status(status).json(mock);
});
OpenAPI Backend supports mocking responses using both OpenAPI example objects and JSON Schema:
paths:
'/pets':
get:
operationId: getPets
summary: List pets
responses:
200:
$ref: '#/components/responses/PetListWithExample'
'/pets/{id}':
get:
operationId: getPetById
summary: Get pet by its id
responses:
200:
$ref: '#/components/responses/PetResponseWithSchema'
components:
responses:
PetListWithExample:
description: List of pets
content:
'application/json':
example:
- id: 1
name: Garfield
- id: 2
name: Odie
PetResponseWithSchema:
description: A single pet
content:
'application/json':
schema:
type: object
properties:
id:
type: integer
minimum: 1
name:
type: string
example: Garfield
The example above will yield:
api.mockResponseForOperation('getPets'); // => { status: 200, mock: [{ id: 1, name: 'Garfield' }, { id: 2, name: 'Odie' }]}
api.mockResponseForOperation('getPetById'); // => { status: 200, mock: { id: 1, name: 'Garfield' }}
See full Mock API example on Express
Contributing
OpenAPI Backend is Free and Open Source Software. Issues and pull requests are more than welcome!