OpenAPI Backend
openapi-backend is a robust and framework-agnostic middleware library for Node.js, designed to streamline API development by leveraging OpenAPI Specification definitions. It provides capabilities for request validation, routing based on operationIds, authentication via security schemes, and automatic response mocking from examples or schemas. The current stable version is 5.16.1, with an active release cadence reflecting continuous development and maintenance. Key differentiators include its agnosticism towards specific web frameworks (e.g., Express, Hapi, Koa, Serverless Lambda), its use of AJV for highly performant JSON Schema validation, and its TypeScript-first design which includes comprehensive type definitions. It operates without generating any code, offering a clean and efficient runtime, and supports OpenAPI 3.1. This library simplifies API implementation by consolidating common backend concerns into a single, declarative tool, minimizing boilerplate code and ensuring adherence to API contracts.
Common errors
-
TypeError: OpenAPIBackend is not a constructor
cause Attempting to use `require()` for a library that is primarily ESM-first, or not correctly importing the default export.fixUse ESM `import OpenAPIBackend from 'openapi-backend';` instead of CommonJS `const OpenAPIBackend = require('openapi-backend');`. -
Error: request validation failed
cause The incoming API request (parameters, headers, body) does not conform to the schema defined in your OpenAPI Specification.fixInspect `c.validation.errors` within your `validationFail` handler to understand the specific schema violations. Adjust the incoming request or the OpenAPI definition accordingly. -
Error: notFound
cause No `operationId` in your OpenAPI definition matches the incoming request path and method, and a generic `notFound` handler has been triggered.fixVerify your OpenAPI definition's `paths` and `operationIds` align with expected API endpoints. Ensure you have registered a handler for the relevant `operationId` or a catch-all `notFound` handler.
Warnings
- breaking Starting with version 5.x, `openapi-backend` requires Node.js version 20.0.0 or higher. Older Node.js versions are not supported.
- gotcha When using `openapi-backend` in a TypeScript project, ensure you use `import type` for importing types (e.g., `Context`, `Request`, `Response`) to prevent issues with runtime imports, especially in environments that don't correctly handle type-only imports.
- gotcha The `api.init()` method must be called after registering all handlers and before handling any requests. Failing to call `init()` will prevent the API backend from properly loading your OpenAPI definition and routing requests.
Install
-
npm install openapi-backend -
yarn add openapi-backend -
pnpm add openapi-backend
Imports
- OpenAPIBackend
const OpenAPIBackend = require('openapi-backend');import OpenAPIBackend from 'openapi-backend';
- Context
import { Context } from 'openapi-backend';import type { Context } from 'openapi-backend'; - Request, Response
import { Request, Response } from 'openapi-backend';import type { Request, Response } from 'openapi-backend';
Quickstart
import OpenAPIBackend from 'openapi-backend';
import express from 'express';
// In a real application, './petstore.yml' would be your OpenAPI definition file.
// For demonstration, we'll use a minimal inline definition.
const api = new OpenAPIBackend({
definition: {
openapi: '3.0.0',
info: { title: 'Petstore API', version: '1.0.0' },
paths: {
'/pets': {
get: {
operationId: 'getPets',
responses: { 200: { description: 'A list of pets' } },
},
},
'/pets/{petId}': {
get: {
operationId: 'getPetById',
parameters: [
{ name: 'petId', in: 'path', required: true, schema: { type: 'string' } },
],
responses: { 200: { description: 'A single pet' } },
},
},
},
},
});
// register your framework specific request handlers here
api.register({
getPets: (c, req, res) => res.status(200).json({ result: 'all pets' }),
getPetById: (c, req, res) => res.status(200).json({ result: `pet with id ${c.request.params.petId}` }),
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();
const app = express();
app.use(express.json()); // Enable JSON body parsing
// Connect openapi-backend to your Express application
app.use((req, res) => api.handleRequest(req, req, res));
const PORT = process.env.PORT ?? 9000;
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
console.log('Try visiting: http://localhost:9000/pets');
console.log('Try visiting: http://localhost:9000/pets/123');
});