all files / swagger-node-runner/fittings/ swagger_router.js

91.07% Statements 51/56
70.97% Branches 22/31
100% Functions 3/3
91.07% Lines 51/56
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102        13×   13× 13×   13× 13×   13×   13×   13× 13×     13×   13× 69×   69× 69×   69×   69×   60× 60×                         69×   69× 69×   69× 57× 57×     12× 12× 12×           12×   12×   12× 12×   12×       12× 12×   12×              
'use strict';
 
var debug = require('debug')('swagger:swagger_router');
var path = require('path');
var assert = require('assert');
var SWAGGER_ROUTER_CONTROLLER = 'x-swagger-router-controller';
var util = require('util');
 
module.exports = function create(fittingDef, bagpipes) {
 
  debug('config: %j', fittingDef);
 
  assert(Array.isArray(fittingDef.controllersDirs), 'controllersDirs must be an array');
  assert(Array.isArray(fittingDef.mockControllersDirs), 'mockControllersDirs must be an array');
 
  var swaggerNodeRunner = bagpipes.config.swaggerNodeRunner;
  var appRoot = swaggerNodeRunner.config.swagger.appRoot;
 
  var mockMode = !!fittingDef.mockMode || !!swaggerNodeRunner.config.swagger.mockMode;
 
  var controllersDirs = mockMode ? fittingDef.mockControllersDirs : fittingDef.controllersDirs;
 
  controllersDirs = controllersDirs.map(function(dir) {
    return path.resolve(appRoot, dir);
  });
 
  var controllerFunctionsCache = {};
 
  return function swagger_router(context, cb) {
    debug('exec');
 
    var operation = context.request.swagger.operation;
    var controllerName = operation[SWAGGER_ROUTER_CONTROLLER] || operation.pathObject[SWAGGER_ROUTER_CONTROLLER];
 
    var controller;
 
    if (controllerName in controllerFunctionsCache) {
 
      debug('controller in cache', controllerName);
      controller = controllerFunctionsCache[controllerName];
 
    } else {
 
      debug('loading controller %s from fs: %s', controllerName, controllersDirs);
      for (var i = 0; i < controllersDirs.length; i++) {
        var controllerPath = path.resolve(controllersDirs[i], controllerName);
        try {
          controller = require(controllerPath);
          controllerFunctionsCache[controllerName] = controller;
          debug('controller found', controllerPath);
        } catch (err) {
          if (!mockMode && err.code === 'MODULE_NOT_FOUND' && i === controllersDirs.length - 1) {
            return cb(err);
          }
          debug('controller not in', controllerPath);
        }
      }
    }
 
    Eif (controller) {
 
      var operationId = operation.definition['operationId'] || context.request.method.toLowerCase();
      var controllerFunction = controller[operationId];
 
      if (controllerFunction && typeof controllerFunction === 'function') {
        debug('running controller');
        return controllerFunction(context.request, context.response, cb);
      }
 
      var msg = util.format('Controller %s doesn\'t export handler function %s', controllerName, operationId);
      Eif (mockMode) {
        debug(msg);
      } else {
        return cb(new Error(msg));
      }
    }
 
    Eif (mockMode) {
 
      var statusCode = parseInt(context.request.get('_mockreturnstatus')) || 200;
 
      var mimetype = context.request.get('accept') || 'application/json';
      var mock = operation.getResponseExample(statusCode, mimetype);
 
      if (mock) {
        debug('returning mock example value', mock);
      } else {
        mock = operation.getResponseSample(statusCode);
        debug('returning mock sample value', mock);
      }
 
      context.headers['Content-Type'] = mimetype;
      context.statusCode = statusCode;
 
      return cb(null, mock);
    }
 
    // for completeness, we should never actually get here
    cb(new Error(util.format('No controller found for %s in %j', controllerName, controllersDirs)));
  }
};