{"id":17092,"library":"exegesis-express","title":"OpenAPI 3.x Express Middleware","description":"exegesis-express provides Express middleware for handling OpenAPI 3.x API definitions, acting as a wrapper around the core `exegesis` library. It offers full support for OpenAPI 3.x.x features including request body parsing (JSON, form-urlencoded), response validation, authentication, and extensibility via a plugin system and custom format validation. The current stable version is 4.0.0, released in December 2021. While not on a fixed release cadence, it typically updates in conjunction with its parent `exegesis` library, incorporating bug fixes, security patches, and Node.js version support changes. Key differentiators include comprehensive OpenAPI 3.x conformance, flexible middleware placement, and robust error handling for API-driven applications.","status":"active","version":"4.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/exegesis-js/exegesis-express","tags":["javascript","express","OpenAPI","oas3","exegesis","typescript"],"install":[{"cmd":"npm install exegesis-express","lang":"bash","label":"npm"},{"cmd":"yarn add exegesis-express","lang":"bash","label":"yarn"},{"cmd":"pnpm add exegesis-express","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Runtime peer dependency for creating and managing web servers; `exegesis-express` functions as Express middleware.","package":"express","optional":false},{"reason":"Core library that `exegesis-express` wraps, providing the OpenAPI 3.x parsing, validation, and routing logic.","package":"exegesis","optional":false}],"imports":[{"note":"Since v4.0.0, Node.js 10+ is required. Modern projects should prefer ESM imports. CommonJS `require` is still supported but less idiomatic for new code.","wrong":"const { middleware } = require('exegesis-express');","symbol":"middleware","correct":"import { middleware } from 'exegesis-express';"},{"note":"For TypeScript projects, import types explicitly for `middleware` options for better type checking and IntelliSense.","symbol":"ExegesisOptions","correct":"import type { ExegesisOptions } from 'exegesis-express';"},{"note":"For TypeScript projects, import the `OpenApiDocument` type when working with OpenAPI specifications in JSON/YAML format programmatically.","symbol":"OpenApiDocument","correct":"import type { OpenApiDocument } from 'exegesis-express';"}],"quickstart":{"code":"import express from 'express';\nimport { middleware } from 'exegesis-express';\nimport path from 'path';\n\nconst openApiDoc = {\n  openapi: '3.0.3',\n  info: {\n    title: 'Example API',\n    version: '1.0.0',\n  },\n  paths: {\n    '/greet': {\n      get: {\n        'x-exegesis-controller': 'GreetingController',\n        operationId: 'greetUser',\n        parameters: [\n          {\n            name: 'name',\n            in: 'query',\n            schema: { type: 'string', default: 'World' },\n            required: false,\n          },\n        ],\n        responses: {\n          '200': {\n            description: 'A greeting message.',\n            content: {\n              'application/json': {\n                schema: { type: 'object', properties: { message: { type: 'string' } } },\n              },\n            },\n          },\n        },\n      },\n    },\n  },\n};\n\n// Create a simple controller file (e.g., controllers/GreetingController.ts)\n// export function greetUser(context) {\n//   const name = context.params.query.name || 'World';\n//   return { message: `Hello, ${name}!` };\n// }\n\nasync function createServer() {\n  const app = express();\n\n  const exegesisMiddleware = await middleware(openApiDoc, {\n    controllers: path.resolve(__dirname, 'controllers'),\n    allowMissingControllers: false,\n    onResponseValidationError: (error) => {\n      console.error('Response validation error:', error);\n    },\n  });\n\n  // Exegesis-express should be placed before any body parsers if you want\n  // it to handle request body parsing itself.\n  app.use(exegesisMiddleware);\n\n  // Catch-all for routes not handled by Exegesis (e.g., 404)\n  app.use((req, res) => {\n    res.status(404).json({ message: 'Not Found' });\n  });\n\n  // Global error handler\n  app.use((err, req, res, next) => {\n    console.error('Unhandled error:', err);\n    res.status(500).json({ message: `Internal server error: ${err.message}` });\n  });\n\n  app.listen(3000, () => {\n    console.log('Server listening on http://localhost:3000');\n    console.log('Try: curl http://localhost:3000/greet?name=Alice');\n  });\n}\n\ncreateServer().catch(console.error);","lang":"typescript","description":"This quickstart sets up an Express server using `exegesis-express` to serve a simple OpenAPI 3.x defined API. It demonstrates how to initialize the middleware with an OpenAPI specification (inline JSON for simplicity), configure controllers, handle response validation errors, and correctly place the middleware within the Express stack."},"warnings":[{"fix":"Upgrade your Node.js version to 12.x or later. For continued Node.js 10 support, pin `exegesis-express` to a version prior to 4.0.0.","message":"Version 4.0.0 dropped support for Node.js 10. Users on older Node.js versions must remain on v3.x or upgrade their Node.js environment.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Review any code that parses or displays validation error messages to ensure compatibility with the new `ajv` messages. Update tests as necessary.","message":"Version 3.0.0 upgraded the underlying `ajv` library to 8.3.0, which may result in changes to validation error messages. This can affect automated tests or client-side error handling that relies on specific error string matching.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Upgrade your Node.js version to 8.x or later. For continued Node.js 6 support, pin `exegesis-express` to a version prior to 2.0.0.","message":"Version 2.0.0 dropped support for Node.js 6. Applications running on Node.js 6 must not upgrade to v2.0.0 or higher.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure `app.use(exegesisMiddleware)` is called before `app.use(express.json())` or similar body parsers. If a body parser runs first, `exegesis-express` will attempt to use `req.body` if it exists.","message":"`exegesis-express` should generally be placed high in your Express middleware stack, *before* any other body-parsing middlewares (like `express.json()` or `body-parser`). This allows `exegesis` to handle request body parsing according to the OpenAPI specification.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Add `x-exegesis-controller: 'YourControllerName'` and `operationId: 'yourOperationFunction'` to your OpenAPI path operations, and ensure `options.controllers` points to the directory containing `YourControllerName.js` (or `.ts`).","message":"OpenAPI paths intended to be handled by `exegesis-express` must define the `x-exegesis-controller` extension and `operationId` on each operation. Without these, `exegesis` cannot map incoming requests to the correct controller functions.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Verify that `options.controllers` in your middleware setup points to the correct directory. Confirm that the controller file exists and exports a function with the exact `operationId` name (e.g., `export function myOperation(...)`). Check the `x-exegesis-controller` value in your OpenAPI definition matches the controller file name (without extension).","cause":"The `operationId` specified in your OpenAPI document does not correspond to an exported function in the designated controller module, or the `x-exegesis-controller` path is incorrect, or `options.controllers` is misconfigured.","error":"Error: No handler found for operationId 'myOperation' for '/my-path'"},{"fix":"Review your OpenAPI specification to ensure that parameters are correctly defined with their `in` property (e.g., `in: 'query'`, `in: 'path'`) and that your controller code correctly accesses them (e.g., `context.params.query.myParam`). Add `required: true` to OpenAPI parameters if they are mandatory.","cause":"This often occurs within a controller function trying to access `context.params.query` or `context.params.path` when a parameter expected is missing or has an incorrect `in` location (e.g., expecting `query` but parameter is `path`).","error":"TypeError: Cannot read properties of undefined (reading 'query')"},{"fix":"Compare the data structure and types returned by your controller's operation function against the OpenAPI response schema (`paths['/your-path'].get.responses['200'].content['application/json'].schema`). Adjust either your controller's return value or the OpenAPI schema to match. If `onResponseValidationError` is set, its callback will be invoked.","cause":"The data returned by your controller function does not conform to the `response` schema defined in your OpenAPI document for that operation, or the `onResponseValidationError` option is firing.","error":"Response validation error: ... must be string (or similar AJV error)"}],"ecosystem":"npm","meta_description":null}