Installations
npm install swagger-routes-express-enhanced
Developer Guide
Typescript
No
Module System
CommonJS
Min. Node Version
>= 6.4.0
Node Version
12.16.1
NPM Version
6.14.5
Score
71.4
Supply Chain
99.3
Quality
75.4
Maintenance
100
Vulnerability
100
License
Releases
Version 3.3.3
Updated on Jan 08, 2025
Version 3.3.2 (upgraded dependencies)
Updated on Jul 30, 2022
Version 3.3.1 (Fixed types)
Updated on Aug 19, 2021
Version 3.3.0 - now with arrays of controllers
Updated on Jan 24, 2021
Version 3.2.1 (Bug fix in types)
Updated on Jul 08, 2020
Version 3.2.0 (TypeScript definitions)
Updated on Jul 06, 2020
Contributors
Unable to fetch Contributors
Languages
JavaScript (100%)
Love this project? Help keep it running — sponsor us today! 🚀
Developer
davesag
Download Statistics
Total Downloads
721
Last Day
1
Last Week
2
Last Month
24
Last Year
91
GitHub Statistics
MIT License
86 Stars
554 Commits
20 Forks
5 Watchers
2 Branches
7 Contributors
Updated on Jan 08, 2025
Bundle Size
28.15 kB
Minified
8.51 kB
Minified + Gzipped
Sponsor this package
Package Meta Information
Latest Version
3.2.2
Package Id
swagger-routes-express-enhanced@3.2.2
Unpacked Size
41.36 kB
Size
13.79 kB
File Count
33
NPM Version
6.14.5
Node Version
12.16.1
Total Downloads
Cumulative downloads
Total Downloads
721
Last Day
0%
1
Compared to previous day
Last Week
-75%
2
Compared to previous week
Last Month
2,300%
24
Compared to previous month
Last Year
-12.5%
91
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Dependencies
1
Dev Dependencies
28
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
:
1npm i swagger-routes-express
Examples
A simple API
Assume the following API route controllers, defined in ./api/index.js
as follows:
1const { name, version, description } = require('../../package.json') 2 3const versions = (req, res) => { 4 res.json([ 5 { 6 version: 1, 7 path: '/api/v1' 8 } 9 ]) 10} 11 12const ping = (req, res) => { 13 res.json({ 14 name, 15 description, 16 version, 17 uptime: process.uptime() 18 }) 19} 20 21module.exports = { ping, versions }
Swagger Version 2 example
Given a Swagger (v2) YAML file api.yml
along the lines of:
1swagger: '2.0' 2info: 3 description: Something about the API 4 version: '1.0.0' 5 title: 'Test API' 6basePath: '/api/v1' 7schemes: 8 - 'https' 9 - 'http' 10paths: 11 /: 12 get: 13 tags: 14 - 'root' 15 summary: 'Get API Version Information' 16 description: 'Returns a list of the available API versions' 17 operationId: 'versions' 18 produces: 19 - 'application/json' 20 responses: 21 200: 22 description: 'success' 23 schema: 24 $ref: '#/definitions/ArrayOfVersions' 25 /ping: 26 get: 27 tags: 28 - 'root' 29 summary: 'Get Server Information' 30 description: 'Returns information about the server' 31 operationId: 'ping' 32 produces: 33 - 'application/json' 34 responses: 35 200: 36 description: 'success' 37 schema: 38 $ref: '#/definitions/ServerInfo' 39definitions: 40 # see https://swagger.io/docs/specification/data-models/data-types 41 APIVersion: 42 type: 'object' 43 properties: 44 version: 45 type: 'integer' 46 format: 'int64' 47 path: 48 type: 'string' 49 ServerInfo: 50 type: 'object' 51 properties: 52 name: 53 type: 'string' 54 description: 55 type: 'string' 56 version: 57 type: 'string' 58 uptime: 59 type: 'number' 60 ArrayOfVersions: 61 type: 'array' 62 items: 63 $ref: '#/definitions/APIVersion'
OpenAPI Version 3 example
1openapi: 3.0.0 2info: 3 description: Something about the API 4 version: 1.0.0 5 title: Test API 6paths: 7 /: 8 get: 9 tags: 10 - root 11 summary: Get API Version Information 12 description: Returns a list of the available API versions 13 operationId: versions 14 responses: 15 '200': 16 description: success 17 content: 18 application/json: 19 schema: 20 $ref: '#/components/schemas/ArrayOfVersions' 21 /ping: 22 get: 23 tags: 24 - root 25 summary: Get Server Information 26 description: Returns information about the server 27 operationId: ping 28 responses: 29 '200': 30 description: success 31 content: 32 application/json: 33 schema: 34 $ref: '#/components/schemas/ServerInfo' 35servers: 36 - url: /api/v1 37components: 38 schemas: 39 APIVersion: 40 type: object 41 properties: 42 version: 43 type: integer 44 format: int64 45 path: 46 type: string 47 ServerInfo: 48 type: object 49 properties: 50 name: 51 type: string 52 description: 53 type: string 54 version: 55 type: string 56 uptime: 57 type: number 58 ArrayOfVersions: 59 type: array 60 items: 61 $ref: '#/components/schemas/APIVersion'
Connecting your Express server
You can connect
your Express
app or router as follows:
1const express = require('express') 2const YAML = require('yamljs') 3const { connector } = require('swagger-routes-express') 4const api = require('./api') 5 6const makeApp = () => { 7 const apiDefinition = YAML.load('api.yml') // load the api as json 8 const connect = connector(api, apiDefinition) // make the connector 9 const app = express() // make the app 10 11 // do any other app stuff, such as wire in passport, use cors etc 12 13 connect(app) // attach the routes 14 15 // add any error handlers last 16 17 return app 18}
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.
1const connect = connector(api, apiDefinition, options)
If you don't pass in any options the defaults are:
1{ 2 security: {}, 3 middleware: {}, 4 onCreateRoute: undefined, 5 apiSeparator: '_', 6 notFound: : require('./routes/notFound'), 7 notImplemented: require('./routes/notImplemented'), 8 rootTag: 'root', // only used in Swagger V2 docs 9 variables: {}, // only used in OpenAPI v3 docs 10 INVALID_VERSION: require('./errors').INVALID_VERSION 11}
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:
1paths: 2 /private 3 get: 4 summary: some private route 5 security: 6 - access: ['read', 'write'] 7 /admin 8 get: 9 summary: some admin route 10 security: 11 - access: ['admin']
Supply a security
option as follows
1const options = { 2 security: { 3 'read,write': readWriteAuthMiddlewareFunction, 4 admin: adminAuthMiddlewareFunction 5 } 6}
Security without scopes
If your path defines security
, and its scopes
array is empty, you use its name in the security
option.
Given:
1paths: 2 /private 3 get: 4 summary: some private route 5 security: 6 - apiKey: []
Supply a security
option like:
1const options = { 2 security: { 3 apiKey: myAuthMiddlewareFunction 4 } 5}
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:
1paths: 2 /my-route 3 get: 4 summary: some route that is exempt from the default security 5 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.
1async function correspondingMiddlewareFunction(req, res, next) {
2 // previously you have added a userId to req (say from an 'Authorization: Bearer token' header)
3 // how you check that the token is valid is up to your app's logic
4 if (await isValidToken(req.user.token)) return next()
5
6 // otherwise reject with an error
7 return res.status(401).json({ error: "I'm afraid you can't do that" })
8}
- More information… (via DuckDuckGo)
Adding other path-level middleware
You can add your own path specific middleware by passing in a middleware
option:
1{ 2 middleware: { 3 myMiddleware: someMiddlewareFunction 4 } 5}
With either Swagger v2 or OpenAPI v3, add an x-middleware
option in the path specification:
1paths: 2 /special: 3 get: 4 summary: some special route 5 x-middleware: 6 - myMiddleware
The someMiddlewareFunction
will be inserted after any Auth Middleware.
Adding hooks
You can supply an onCreateRoute
handler function with the options with signature
1const onCreateRoute = (method, descriptor) => { 2 const [path, ...handlers] = descriptor 3 console.log('created route', method, path, handlers) 4}
The method will be one of 'get', 'post', 'patch', 'put', or 'delete'.
The descriptor
is an array of:
1;[ 2 path, // a string. Swagger param formats will have been converted to express route formats. 3 security, // an auth middleware function (if needed) 4 ...middleware, // other middleware functions (if supplied) 5 controller // then finally the route controller function 6]
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:
1{ 2 info: { name, version, description }, 3 paths: { [method]: ['/array', '/of', '/normalised/:paths'] } 4}
as follows:
1const YAML = require('yamljs') 2const { summarise } = require('swagger-routes-express') 3 4const apiDefinition = YAML.load('api.yml') 5const apiSummary = summarise(apiDefinition)
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
1const connector = require('swagger-routes-express')
The new way
1const { connector } = require('swagger-routes-express')
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
1npm run lint
Contributing
Please see the contributing notes.

No vulnerabilities found.
Reason
security policy file detected
Details
- Info: security policy file detected: SECURITY.md:1
- Info: Found linked content: SECURITY.md:1
- Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1
- Info: Found text in security policy: SECURITY.md:1
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
0 existing vulnerabilities detected
Reason
SAST tool detected but not run on all commits
Details
- Info: SAST configuration detected: CodeQL
- Warn: 0 commits out of 30 are checked with a SAST tool
Reason
Found 1/2 approved changesets -- score normalized to 5
Reason
6 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1
- Info: no jobLevel write permissions found
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/davesag/swagger-routes-express/codeql-analysis.yml/develop?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/davesag/swagger-routes-express/codeql-analysis.yml/develop?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/davesag/swagger-routes-express/codeql-analysis.yml/develop?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:62: update your workflow using https://app.stepsecurity.io/secureworkflow/davesag/swagger-routes-express/codeql-analysis.yml/develop?enable=pin
- Info: 0 out of 4 GitHub-owned GitHubAction dependencies pinned
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Score
6
/10
Last Scanned on 2025-02-10
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More