/* eslint-disable no-process-env */ /* eslint-disable no-unneeded-ternary */ 'use strict'; /** * The core page for the configuration and deployment of the API server for * the Web Console. * * The API server is powered by a Swagger API definition: * @see {@link http://swagger.io} * * Express middleware is then used to take the Swagger API definition and * handle most of the essential but repetitive parts of the API: * - Connecting routes to handler functions * - Checking security * - Validating paramters * - Validating reponses * - Managing CORS responses * * In development mode there is also middleware to serve interactive API * documentation and the API doc itself. */ const _ = require('lodash'); const compression = require('compression'); const morgan = require('morgan'); // Logging middleware by expressjs const express = require('express'); const router = express.Router(); const swaggerTools = require('swagger-tools'); const RateLimit = require('express-rate-limit'); const config = require(global.configFile); const security = require('./int_security.js'); const errorHandler = require(global.pathPrefix + '../swagger_api/api_error_handler.js'); const initMorgan = require(global.pathPrefix + '../utils/init_morgan.js'); // // Export the router // module.exports = { init }; // // Swagger Router configuration // @see {@link https://github.com/apigee-127/swagger-tools/blob/master/docs/Middleware.md#swagger-router} // const swaggerRouterOptions = { // @member {String} - path to the controllers controllers: global.rootPath + 'integration_api/controllers', // @member {Boolean} - enable autogenerated stubs for dev environment useStubs: process.env.NODE_ENV === 'development' }; // // Swagger Validator configuration options // @see {@link https://github.com/apigee-127/swagger-tools/blob/master/docs/Middleware.md#swagger-validator} // const swaggerValidatorOptions = { // @member{Boolean} - validate responses as well as requests // swagger stubs don't match the validation entirely, so responses can't // be validated if they are enabled. validateResponse: swaggerRouterOptions.useStubs ? true : true }; // // Load the Swagger API defintion file // const swaggerDoc = require('./integration_swagger_def.json'); // // We are going to be used as an express router under /int so remove that from // the front of the base path in the swagger API definition. If we don't // remove it we end up with a path of /int/int/v0/... // swaggerDoc.basePath = swaggerDoc.basePath.replace('/int', ''); /** * Function to intialise the swagger tools for serving the swagger-based * integration API. * * @returns {Object} - router with middleware included */ function init() { // // Initialise morgan configuration // initMorgan.init(); // // Rate limiting options // Warning: we must clone the value from config so that when we change the // keyGenerator etc. it doesn't affect other places using the same // config. // const rateLimitConfig = _.clone(config.rateLimits.api); rateLimitConfig.keyGenerator = function(req) { // // Limit per-token if we have a token. Otherwise limit per ip // const token = req.header('authorization'); if (token) { return token; } else { return req.ip; } }; rateLimitConfig.handler = function(req, res) { // Always send a JSON response res.status(rateLimitConfig.statusCode).json({ code: 30500, info: 'Rate limit reached. Please wait and try again' }); }; const limiter = new RateLimit(rateLimitConfig); // // Initialize the Swagger middleware from the Swagger API definition. // This is asynchronous so we need to wait until its done before configuring // all the express middleware we will use for managing the API // swaggerTools.initializeMiddleware(swaggerDoc, (middleware) => { // // Compression middleware // router.use(compression()); // // Logging middleware // router.use(morgan('bridge-combined')); // // Middleware to interpret Swagger resources and attach metadata to request // - must be first in swagger - tools middleware chain // router.use(middleware.swaggerMetadata()); /* * Rate Limiting */ router.use(limiter); // // Middleware to enforce the security rules definedin the Swagger file. // Ignore lack of camel case for the swagger defines: // jshint -W106 router.use(middleware.swaggerSecurity({ bearer: security.bearer })); // // Middleware to validate Swagger request and response parameters // router.use(middleware.swaggerValidator(swaggerValidatorOptions)); // // Middleware to route validated requests to the appropriate controller // router.use(middleware.swaggerRouter(swaggerRouterOptions)); // // Middleware to serve the Swagger documents and Swagger UI. // This provides access to the Swagger UI at /api/docs and the full // swagger json file at /api/api-docs // Note: only enabled in development environments // if (process.env.NODE_ENV === 'development') { router.use(middleware.swaggerUi()); } // // Error handler middleware to correct server errors as JSON if needed // router.use(errorHandler.errorHandlerMiddleware); // // Stop any requests that didn't get handled above going any further. // This only applies to requests under this router, so no other part of // server could handle it. // router.use((req, res) => { res.status(404).json({ code: 30000, info: 'API path not found' }); }); }); return router; }