diff --git a/fittings/swagger_router.js b/fittings/swagger_router.js index 57d55df..0b1c5ce 100644 --- a/fittings/swagger_router.js +++ b/fittings/swagger_router.js @@ -5,6 +5,7 @@ var path = require('path'); var assert = require('assert'); var SWAGGER_ROUTER_CONTROLLER = 'x-swagger-router-controller'; var util = require('util'); +var translateResponse = require('../lib/connect_middleware').translateResponse; module.exports = function create(fittingDef, bagpipes) { @@ -20,14 +21,14 @@ module.exports = function create(fittingDef, bagpipes) { var controllersDirs = mockMode ? fittingDef.mockControllersDirs : fittingDef.controllersDirs; - controllersDirs = controllersDirs.map(function(dir) { + controllersDirs = controllersDirs.map(function (dir) { return path.resolve(appRoot, dir); }); var controllerFunctionsCache = {}; return function swagger_router(context, cb) { - debug('exec'); + debug('exec %s', context.request.swagger.operation.ptr || context.request.swagger.operation.pathObject.ptr); var operation = context.request.swagger.operation; var controllerName = operation[SWAGGER_ROUTER_CONTROLLER] || operation.pathObject[SWAGGER_ROUTER_CONTROLLER]; @@ -47,56 +48,86 @@ module.exports = function create(fittingDef, bagpipes) { try { controller = require(controllerPath); controllerFunctionsCache[controllerName] = controller; - debug('controller found', controllerPath); + debug('controller found', path.relative(appRoot, controllerPath)); break; } catch (err) { + debug('controller not in', path.relative(appRoot, controllerPath)); if (!mockMode && i === controllersDirs.length - 1) { return cb(err); } - debug('controller not in', controllerPath); } } } + if (!controller && mockMode) { + controller = controllerFunctionsCache[controllerName] = {}; + debug('created mock controller %s', controllerName); + } + if (controller) { var operationId = operation.definition['operationId'] || context.request.method.toLowerCase(); var controllerFunction = controller[operationId]; + if (!controllerFunction && mockMode) { + controllerFunction = controller[operationId] = createMockControllerFunction(fittingDef, bagpipes); + debug('created mock controller function %s.%s', controllerName, operationId); + } + if (controllerFunction && typeof controllerFunction === 'function') { - debug('running controller'); + debug('running controller %s.%s', controllerName, operationId); return controllerFunction(context.request, context.response, cb); } - var msg = util.format('Controller %s doesn\'t export handler function %s', controllerName, operationId); - if (mockMode) { - debug(msg); - } else { - return cb(new Error(msg)); - } + debug(util.format('Controller %s doesn\'t export handler function %s', controllerName, operationId)); + return cb(new Error(msg)); } - if (mockMode) { + // for completeness, we should never actually get here + cb(new Error(util.format('No controller found for %s in %j', controllerName, controllersDirs))); + } +}; + +function createMockControllerFunction(fittingDef, bagpipes) { + var swaggerNodeRunner = bagpipes.config.swaggerNodeRunner; + var appRoot = swaggerNodeRunner.config.swagger.appRoot; + + var mockModeNoCallback = !!fittingDef.mockModeNoCallback || !!swaggerNodeRunner.config.swagger.mockModeNoCallback; + + return function default_mock_controller(request, response, cb) { + debug('exec default_mock_controller') - var statusCode = parseInt(context.request.get('_mockreturnstatus')) || 200; + var operation = request.swagger.operation; + var controllerName = operation[SWAGGER_ROUTER_CONTROLLER] || operation.pathObject[SWAGGER_ROUTER_CONTROLLER]; - var mimetype = context.request.get('accept') || 'application/json'; - var mock = operation.getResponseExample(statusCode, mimetype); + var statusCode = parseInt(request.get('_mockreturnstatus')) || 200; - if (mock) { - debug('returning mock example value', mock); + var mimetype = request.get('accept'); + if (!mimetype || mimetype === '*/*') { + if (!operation.produces || !operation.produces.length || operation.produces.indexOf('application/json') >= 0) { + mimetype = 'application/json'; } else { - mock = operation.getResponseSample(statusCode); - debug('returning mock sample value', mock); + mimetype = operation.produces[0]; } + } - context.headers['Content-Type'] = mimetype; - context.statusCode = statusCode; + var mock = operation.getResponseExample(statusCode, mimetype); - return cb(null, mock); + if (mock) { + debug('returning mock example value', mock); + } else { + mock = operation.getResponseSample(statusCode); + debug('returning mock sample value', mock); } - // for completeness, we should never actually get here - cb(new Error(util.format('No controller found for %s in %j', controllerName, controllersDirs))); - } -}; + response.setHeader('Content-Type', mimetype); + + response.statusCode = statusCode; + + if (mockModeNoCallback) { + response.end(translateResponse(mock, mimetype)); + } else { + cb(null, mock); + } + }; +} \ No newline at end of file diff --git a/lib/connect_middleware.js b/lib/connect_middleware.js index f9e41f7..f2e5fae 100644 --- a/lib/connect_middleware.js +++ b/lib/connect_middleware.js @@ -130,6 +130,7 @@ function translate(output, mimeType) { return util.inspect(output) } } +module.exports.translateResponse = translate; function hookResponseForValidation(context, eventEmitter) {