195 lines
6.0 KiB
JavaScript
195 lines
6.0 KiB
JavaScript
/* 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;
|
|
}
|