diff --git a/examples/petstore/controllers/Pet.js b/examples/petstore/controllers/Pet.js index 91356641a7..2f5c8955c8 100644 --- a/examples/petstore/controllers/Pet.js +++ b/examples/petstore/controllers/Pet.js @@ -3,8 +3,7 @@ var utils = require('../utils/writer.js'); var Pet = require('../services/PetService'); -module.exports.addPet = function addPet (req, res, next) { - var body = req.body; +module.exports.addPet = function addPet (req, res, next, body) { Pet.addPet(body) .then(function (response) { utils.writeJson(res, response); @@ -14,10 +13,7 @@ module.exports.addPet = function addPet (req, res, next) { }); }; - -module.exports.findPetsByStatus = function findPetsByStatus (req, res, next) { - var status = req.query.status[0]; - var sessionid = req.cookies.sessionId; +module.exports.findPetsByStatus = function findPetsByStatus (req, res, next, status, sessionid) { Pet.findPetsByStatus(status,sessionid) .then(function (response) { @@ -28,9 +24,7 @@ module.exports.findPetsByStatus = function findPetsByStatus (req, res, next) { }); }; -module.exports.getPetById = function getPetById (req, res, next) { - - var petId = req.openapi.pathParams['petId']; +module.exports.getPetById = function getPetById (req, res, next, petId) { Pet.getPetById(petId) .then(function (response) { utils.writeJson(res, response); diff --git a/package.json b/package.json index 226e906758..14fe6a8802 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "debug": "^4.1.1", "serve-static": "^1.14.1", "express": "^4.17.1", - "express-openapi-validator": "^3.2.3", + "express-openapi-validator": "^3.6.7", "js-yaml": "^3.13.1", "lodash": "^4.17.15", "morgan": "^1.9.1", diff --git a/src/middleware/express.app.config.ts b/src/middleware/express.app.config.ts index cf6a77e00a..be99cb91ba 100644 --- a/src/middleware/express.app.config.ts +++ b/src/middleware/express.app.config.ts @@ -6,6 +6,7 @@ import cookieParser = require('cookie-parser'); import bodyParser = require('body-parser'); import { SwaggerUI } from './swagger.ui'; import { SwaggerRouter } from './swagger.router'; +import { SwaggerParameters } from './swagger.parameters'; import * as logger from 'morgan'; import * as fs from 'fs'; import * as jsyaml from 'js-yaml'; @@ -43,6 +44,7 @@ export class ExpressAppConfig { }) .install(this.app) .then(() => { + this.app.use(new SwaggerParameters().checkParameters()); this.app.use(new SwaggerRouter().initialize(this.routingOptions)); this.app.use((err, req, res, next) => { diff --git a/src/middleware/swagger.parameters.ts b/src/middleware/swagger.parameters.ts new file mode 100644 index 0000000000..230d0b20ed --- /dev/null +++ b/src/middleware/swagger.parameters.ts @@ -0,0 +1,61 @@ +'use strict'; + +import {isEmpty} from 'lodash'; + +export class SwaggerParameters { + checkParameters() { + const concatArrays = (array, arrayToAttach) => { + if (isEmpty(arrayToAttach)) { + return array; + } + return array.concat(arrayToAttach); + }; + + return (req, res, next) => { + if (!req.openapi || !req.openapi.schema || !req.openapi.schema.parameters) { + next(); + return; + } + let swaggerParameters = Array(); + const queryParams = Array(); + const headerParams = Array(); + const cookieParams = Array(); + const pathParams = Array(); + + swaggerParameters.push(req); + swaggerParameters.push(res); + swaggerParameters.push(next); + + if (!isEmpty(req.body)) { + swaggerParameters.push(req.body); + } + + if (!isEmpty(req.openapi.pathParams)) { + Object.keys(req.openapi.pathParams).forEach(function(key) { + pathParams.push(req.openapi.pathParams[key]); + }); + } + + const parameters = req.openapi.schema.parameters; + for (let i = 0; i < parameters.length; i++) { + const parameter = parameters[i]; + if (parameter.in === 'query') { + queryParams.push(req.query[parameter.name]); + } else if (parameter.in === 'cookie') { + cookieParams.push(req.cookies[parameter.name]); + } else if (parameter.in === 'header') { + headerParams.push(req.headers[parameter.name]); + } + } + + swaggerParameters = concatArrays(swaggerParameters, queryParams); + swaggerParameters = concatArrays(swaggerParameters, pathParams); + swaggerParameters = concatArrays(swaggerParameters, headerParams); + swaggerParameters = concatArrays(swaggerParameters, cookieParams); + + req.openapi.swaggerParameters = swaggerParameters; + + next(); + } + } +} diff --git a/src/middleware/swagger.router.ts b/src/middleware/swagger.router.ts index 6a0658cf09..bb74b932fc 100644 --- a/src/middleware/swagger.router.ts +++ b/src/middleware/swagger.router.ts @@ -9,14 +9,6 @@ const debug = Debug("oas3-tools:routing"); export class SwaggerRouter { - getHandlerName (req) { - if (req.openapi.schema['x-swagger-router-controller']) { - return req.openapi.schema['x-swagger-router-controller'] + '_' + (req.openapi.schema.operationId ? req.openapi.schema.operationId : req.method.toLowerCase()); - } else { - return req.openapi.schema.operationId; - } - } - handlerCacheFromDir(dirOrDirs: any) { const handlerCache: object = {}; const jsFileRegex = /\.(coffee|js|ts)$/; @@ -33,7 +25,7 @@ export class SwaggerRouter { each(dirs, function (dir) { each(fs.readdirSync(dir), function (file: string) { const controllerName: string = file.replace(jsFileRegex, ''); - var controller: string; + let controller: string; if (file.match(jsFileRegex) && file.indexOf(".test.js") === -1) { controller = require(path.resolve(path.join(dir, controllerName))); @@ -44,7 +36,7 @@ export class SwaggerRouter { if (isPlainObject(controller)) { each(controller, function (value, name) { - var handlerId = controllerName + '_' + name; + let handlerId = controllerName + '_' + name; debug(' %s%s', handlerId, @@ -62,12 +54,6 @@ export class SwaggerRouter { return handlerCache; } - send405(req, res, next) { - var err = new Error('Route defined in OpenAPI specification (' + req.openapi.openApiRoute + ') but there is no defined on' + req.method.toUpperCase() + ' operation.'); - res.statusCode = 405; - return next(err); - } - initialize(options) { var handlerCache = {}; @@ -97,14 +83,25 @@ export class SwaggerRouter { handlerCache = this.handlerCacheFromDir(options.controllers); } - const getHandlerName = this.getHandlerName; - const send405 = this.send405; + const getHandlerName = (req) => { + if (req.openapi.schema['x-swagger-router-controller']) { + return req.openapi.schema['x-swagger-router-controller'] + '_' + (req.openapi.schema.operationId ? req.openapi.schema.operationId : req.method.toLowerCase()); + } else { + return req.openapi.schema.operationId; + } + }; + + const send405 = (req, res, next) => { + let err = new Error('Route defined in OpenAPI specification (' + req.openapi.openApiRoute + ') but there is no defined on' + req.method.toUpperCase() + ' operation.'); + res.statusCode = 405; + return next(err); + }; - return function swaggerRouter (req, res, next) { - var operation = req.openapi ? req.openapi.schema.operationId : undefined; - var handler; - var handlerName; - var rErr; + return (req, res, next) => { + let operation = req.openapi ? req.openapi.schema.operationId : undefined; + let handler; + let handlerName; + let rErr; debug('%s %s', req.method, req.url); debug(' Will process: %s', isUndefined(operation) ? 'no' : 'yes'); @@ -123,27 +120,22 @@ export class SwaggerRouter { if (!isUndefined(handler)) { try { - return handler(req, res, next); + return handler.apply(this, req.openapi.swaggerParameters); } catch (err) { rErr = err; - debug('Handler threw an unexpected error: %s\n%s', err.message, err.stack); } } else if (options.ignoreMissingHandlers !== true) { rErr = new Error('Cannot resolve the configured swagger-router handler: ' + handlerName); - res.statusCode = 500; } } else { debug(' No handler for method: %s', req.method); - return send405(req, res, next); } - if (rErr) { debugError(rErr, debug); } - return next(rErr); }; };