swagger-routes-express
Connect Express
route controllers to restful paths using a Swagger
v2 or OpenAPI
v3 definition file.
Prerequisites
This library assumes you are using:
Install
Add swagger-routes-express
as a dependency
:
npm i swagger-routes-express
Examples
A simple API
Assume the following API route controllers, defined in ./api/index.js
as follows:
const name version description = const versions = { res} const ping = { res} moduleexports = ping versions
Swagger Version 2 example
Given a Swagger (v2) YAML file api.yml
along the lines of:
swagger: '2.0'info: description: Something about the API version: '1.0.0' title: 'Test API'basePath: '/api/v1'schemes: - 'https' - 'http'paths: /: get: tags: - 'root' summary: 'Get API Version Information' description: 'Returns a list of the available API versions' operationId: 'versions' produces: - 'application/json' responses: 200: description: 'success' schema: $ref: '#/definitions/ArrayOfVersions' /ping: get: tags: - 'root' summary: 'Get Server Information' description: 'Returns information about the server' operationId: 'ping' produces: - 'application/json' responses: 200: description: 'success' schema: $ref: '#/definitions/ServerInfo'definitions: # see https://swagger.io/docs/specification/data-models/data-types APIVersion: type: 'object' properties: version: type: 'integer' format: 'int64' path: type: 'string' ServerInfo: type: 'object' properties: name: type: 'string' description: type: 'string' version: type: 'string' uptime: type: 'number' ArrayOfVersions: type: 'array' items: $ref: '#/definitions/APIVersion'
OpenAPI Version 3 example
openapi: 3.0.0info: description: Something about the API version: 1.0.0 title: Test APIpaths: /: get: tags: - root summary: Get API Version Information description: Returns a list of the available API versions operationId: versions responses: '200': description: success content: application/json: schema: $ref: '#/components/schemas/ArrayOfVersions' /ping: get: tags: - root summary: Get Server Information description: Returns information about the server operationId: ping responses: '200': description: success content: application/json: schema: $ref: '#/components/schemas/ServerInfo'servers: - url: /api/v1components: schemas: APIVersion: type: object properties: version: type: integer format: int64 path: type: string ServerInfo: type: object properties: name: type: string description: type: string version: type: string uptime: type: number ArrayOfVersions: type: array items: $ref: '#/components/schemas/APIVersion'
Connecting your Express server
You can connect
your Express
app or router as follows:
const express = const YAML = const connector = const api = const makeApp = { const apiDefinition = YAML // load the api as json const connect = // make the connector const app = // make the app // do any other app stuff, such as wire in passport, use cors etc // attach the routes // add any error handlers last return app}
With the result that requests to GET /
will invoke the versions
controller and a request to /ping
will invoke the ping
controller.
Options
You can pass in an optional options
object as a third parameter to the connector
function.
const connect =
If you don't pass in any options the defaults are:
security: {} middleware: {} onCreateRoute: undefined apiSeparator: '_' notFound: : notImplemented: rootTag: 'root' // only used in Swagger V2 docs variables: {} // only used in OpenAPI v3 docs INVALID_VERSION: INVALID_VERSION
Adding security middleware handlers
If your swagger document defines security, you can map this to your own Auth Middleware by passing in a security
option to the connector
.
Security with scopes
For example if your path defines oAuth style security
like:
paths: /private get: summary: some private route security: - access: ['read', 'write'] /admin get: summary: some admin route security: - access: ['admin']
Supply a security
option as follows
const options = security: 'read,write': readWriteAuthMiddlewareFunction admin: adminAuthMiddlewareFunction
Security without scopes
If your path defines security
, and its scopes
array is empty, you use its name in the security
option.
Given:
paths: /private get: summary: some private route security: - apiKey: []
Supply a security
option like:
const options = security: apiKey: myAuthMiddlewareFunction
Global security definition
Both Swagger V2 and OpenAPI V3 allow you to define global security
. The global security
definition will be applied if there is no path-specific one defined.
Exempting a path from global security
If you've defined global security
but wish to exempt a specific path, then you can configure the path like:
paths: /my-route get: summary: some route that is exempt from the default security security: []
Further reading on Swagger and security
Notes
- Only the first security option is used, the others are ignored. Your Auth Middleware function must handle any alternative authentication schemes.
- Scopes, if supplied, are sorted alphabetically.
What's an Auth Middleware function?
An Auth Middleware Function is simply an Express Middleware function that checks to see if the user making the request is allowed to do so.
How this actually works in your server's case is going to be completely application specific, but the general idea is your app needs to be able to log users in, or accept a token from a header, or somehow otherwise stick a user id, or some roles, into req.user
or req.session.user
or something like that. There are dozens of ways to do this. I recommend using something like Passport to handle the specifics.
Your Auth Middleware then just needs to check that the user / roles you've stored corresponds with what you'd like to allow that user to do.
{ // previously you have added a userId to req (say from an 'Authorization: Bearer token' header) // how you check that the token is valid is up to your app's logic if await return // otherwise reject with an error return resstatus401}
- More information… (via DuckDuckGo)
Adding other path-level middleware
You can add your own path specific middleware by passing in a middleware
option:
middleware: myMiddleware: someMiddlewareFunction
With either Swagger v2 or OpenAPI v3, add an x-middleware
option in the path specification:
paths: /special: get: summary: some special route x-middleware: - myMiddleware
The someMiddlewareFunction
will be inserted after any Auth Middleware.
Adding hooks
You can supply an onCreateRoute
handler function with the options with signature
const onCreateRoute = { const path ...handlers = descriptor console}
The method will be one of 'get', 'post', 'patch', 'put', or 'delete'.
The descriptor
is an array of:
; path // a string. Swagger param formats will have been converted to express route formats. security // an auth middleware function (if needed) ...middleware // other middleware functions (if supplied) controller // then finally the route controller function
Mapping to nested API routes
If your ./api
folder contains nested controllers such as:
/api/v1/createThing.js
It's not uncommon for ./index.js
to expose this as v1_createThing
, but in swagger the operationId
might specify it as v1/createThing
.
You can supply your own apiSeparator
option in place of _
to map from /
.
Missing Route Controllers
If a route controller is defined as an operationId
in Swagger but there is no corresponding controller, a default notImplemented
controller will be inserted that simply responds with a 501
error. You can also specify your own notImplemented
controller in options
.
If no operationId
is supplied for a path then a default notFound
controller that responds with a 404
status will be inserted. You can also specify your own notFound
controller in options
.
Base paths
Swagger Version 2
For the root path /
we check the route's tags
. If the first tag
defined for a path is 'root'
we don't inject the api basePath
, otherwise we do. You can define your own rootTag
option to override this behaviour.
OpenAPI Version 3
The OpenAPI V3 format allows you to define both a default servers
array, and path
specific servers
arrays. The url
fields in those arrays are parsed, ignoring any absolute URLS (as they are deemed to refer to controllers external to this API Server).
The spec allows you to include template variables in the servers
' url
field. To accomodate this you can supply a variables
option in options
. Any variables you specify will be substituted.
Generating API summary information
You can generate a summary of your Swagger v2 or OpenAPI v3 API specification in the form:
info: name version description paths: method: '/array' '/of' '/normalised/:paths'
as follows:
const YAML = const summarise = const apiDefinition = YAMLconst apiSummary =
Upgrading from Swagger Routes Express V2 to V3
These docs refer to Version 3 of Swagger Routes Express which changed the way you invoke the connector
.
The old way
const connector =
The new way
const connector =
Development
Branches
Branch | Status | Coverage | Audit | Notes |
---|---|---|---|---|
develop |
Work in progress | |||
master |
Latest stable release |
Prerequisites
- NodeJS — Ideally you will develop with version
12.18.2 (LTS)
or better, but it will work with node versions going back to version6.4.0
.
Test it
npm test
— runs the unit tests.npm run test:unit:cov
- run the unit tests with coverage.npm run test:mutants
- run mutation testing of the unit tests.
Lint it
npm run lint
Contributing
Please see the contributing notes.