var createRunner = function (doc, callback) { Runner.create({ appRoot: '.', startWithErrors: true, swagger: doc, fittingsDirs: [ './fittings' ], defaultPipe: 'swagger_controllers', swaggerControllerPipe: 'swagger_controllers', bagpipes: { '_swagger_params_parser': { name: 'swagger_params_parser', jsonOptions: { type: ['json', 'application/*+json'], limit: 5 * 1024 * 1024 } }, _router: { name: 'swagger_router', mockMode: false, mockControllersDirs: [ 'api/mocks' ], controllersDirs: [ './controllers' ] }, 'any_controllers': [ 'cors', 'any_handler', '_swagger_params_parser', '_router' ], 'swagger_controllers': [ 'cors', '_swagger_params_parser', '_router' ] } }, function (err, runner) { if (err) { callback(err); return; } runner.expressMiddleware().register(app); callback(); }); };
initialize: function initialize(cb) { var config = { appRoot: sails.config.appPath, configDir: sails.config.paths.config, controllersDirs: [sails.config.paths.controllers], mockControllersDirs: [path.resolve(sails.config.paths.controllers, '..', 'mocks')], swaggerFile: path.resolve(sails.config.paths.controllers, '..', 'swagger', "swagger.yaml") }; SwaggerRunner.create(config, function(err, runner) { if (err) { return cb(err); } var sailsMiddleware = runner.sailsMiddleware(); chain = sailsMiddleware.chain(); sails.hooks['swagger-sails-hook'].runner = runner; return cb(); }); },
/** * Configure swagger node runner with the app. * It loads the swagger specification and maps everything with an active express app. * * @module * @see Parent: {@link config} * @requires fs * @requires js-yaml * @requires path * @requires swagger-node-runner * @param {Object} app - An express app to which map the swagger details * @param {Object} config - Application Configurations * @param {Object} logger - Application Logger * @param {Object} scope - Application Scope * @param {function} cb - Callback function * @returns {void} */ function bootstrapSwagger(app, config, logger, scope, cb) { // Register modules to be used in swagger fittings require('../helpers/swagger_module_registry').bind(scope); // Register the express middleware(s) // Restrict access based on rules app.use(middleware.applyAPIAccessRules.bind(null, config)); // Bind each request/response pair to its own domain app.use(require('express-domain-middleware')); // Maximum 2mb body size for POST type requests app.use(bodyParser.raw({ limit: '2mb' })); // Maximum 2mb body size for json type requests app.use(bodyParser.json({ limit: '2mb' })); // Maximum 2mb body size for URL encoded requests app.use( bodyParser.urlencoded({ extended: true, limit: '2mb', parameterLimit: 5000, }) ); // Allow method override for any request app.use(methodOverride()); // Custom query param parsing app.use(middleware.queryParser()); // Log request message app.use(middleware.logClientConnections.bind(null, logger)); /** * Instruct browser to deny display of <frame>, <iframe> regardless of origin. * * RFC -> https://tools.ietf.org/html/rfc7034 */ app.use( middleware.attachResponseHeader.bind(null, 'X-Frame-Options', 'DENY') ); /** * Set Content-Security-Policy headers. * * frame-ancestors - Defines valid sources for <frame>, <iframe>, <object>, <embed> or <applet>. * * W3C Candidate Recommendation -> https://www.w3.org/TR/CSP/ */ app.use( middleware.attachResponseHeader.bind( null, 'Content-Security-Policy', "frame-ancestors 'none'" ) ); // Log if there is any error app.use(middleware.errorLogger.bind(null, logger)); // Load Swagger controllers and bind the scope var controllerFolder = '/api/controllers/'; fs.readdirSync(config.root + controllerFolder).forEach(file => { if (path.basename(file) !== 'index.js') { // eslint-disable-next-line import/no-dynamic-require require(config.root + controllerFolder + file)(scope); } }); var swaggerConfig = { appRoot: config.root, configDir: `${config.root}/config/swagger`, swaggerFile: path.join(`${config.root}/schema/swagger.yml`), enforceUniqueOperationId: true, startWithErrors: false, startWithWarnings: true, }; // Swagger express middleware SwaggerRunner.create(swaggerConfig, (errors, runner) => { if (errors) { // Ignore unused definition warning errors.validationWarnings = _.filter( errors.validationWarnings, error => error.code !== 'UNUSED_DEFINITION' ); // Some error occurred in configuring the swagger if (!_.isEmpty(errors.validationErrors)) { logger.error('Swagger Validation Errors:'); logger.error(errors.validationErrors); } if (!_.isEmpty(errors.validationWarnings)) { logger.error('Swagger Validation Warnings:'); logger.error(errors.validationWarnings); } if ( !_.isEmpty(errors.validationErrors) || !_.isEmpty(errors.validationWarnings) ) { cb(errors); return; } } // Swagger express middleware var swaggerExpress = runner.expressMiddleware(); // Check the response and act appropriately on error runner.on('responseValidationError', validationResponse => { // TODO: Troubleshoot why default validation hook considers json response as string response if (validationResponse.errors[0].code !== 'INVALID_RESPONSE_BODY') { logger.error('Swagger Response Validation Errors:'); logger.error(validationResponse.errors[0].errors); } }); // Install middleware swaggerExpress.register(app); // To be used in test cases or getting configuration runtime app.swaggerRunner = runner; // Managing all the queries which were not caught by previous middlewares. app.use((req, res, next) => { // We need to check if the response is already handled by some other middlewares/fittings/controllers // In case not, we consider it as 404 and send default response // res.headersSent is a patch, and only works if above middlewares set some header no matter the status code // Another possible workaround would be res.bodySize === 0 if (!res.headersSent) { res.status(404); res.json({ description: 'Page not found' }); } next(); }); swaggerHelper .getResolvedSwaggerSpec() .then(resolvedSchema => { // Successfully mounted the swagger runner cb(null, { swaggerRunner: runner, definitions: resolvedSchema.definitions, }); }) .catch(reason => { cb(reason); }); }); }
'use strict'; var SwaggerRunner = require('swagger-node-runner'); var Hapi = require('hapi'); var app = new Hapi.Server(); module.exports = app; // for testing var config = { appRoot: __dirname // required config }; SwaggerRunner.create(config, function(err, runner) { if (err) { throw err; } var port = process.env.PORT || 10010; app.connection({ port: port }); app.register(runner.hapiMiddleware().plugin, function(err) { if (err) { return console.error('Failed to load plugin:', err); } app.start(function() { console.log('try this:\ncurl http://127.0.0.1:' + port + '/hello?name=Scott'); }); }); });