bridge-node-server/node_server/integration_api/int_api_server.js

195 lines
6.0 KiB
JavaScript
Raw Normal View History

2018-06-24 20:15:03 +00:00
/* 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;
}