UNPKG

sails

Version:

API-driven framework for building realtime apps, using MVC conventions (based on Express and Socket.io)

194 lines (156 loc) 7.34 kB
/** * Module dependencies */ var Path = require('path'); var util = require('util'); var flaverr = require('flaverr'); var _ = require('@sailshq/lodash'); /** * getBuiltInHttpMiddleware() * * Return a dictionary containing all built-in middleware in Sails, * applying configuration along the way. * * @param {Router} expressRouterMiddleware [i.e. `app.router`] * @param {SailsApp} sails * @return {Dictionary} * @property {Function} * * @param {Request} req * @param {Response} res * @param {Function} next */ module.exports = function getBuiltInHttpMiddleware (expressRouterMiddleware, sails) { // Note that the environment of a Sails app is officially determined by // `sails.config.environment`. Normally, that is identical to what you'll // find inside `process.env.NODE_ENV`. // // However it is possible for NODE_ENV and `sails.config.environment to vary // (e.g. `sails.config.environment==='staging'` and `process.env.NODE_ENV==='production'`). // // Some middleware _depends on the NODE_ENV environment variable_ to determine // its behavior. Since NODE_ENV may have been set automatically, this is why the // relevant requires are included _within_ this function, rather than up top. // // This is also why the NODE_ENV environment variable is used here to determine // whether or not to consider the app "in production". This way, if you set // `NODE_ENV=production` explicitly, you can still use something like "staging" // or "sandbox" for your `sails.config.environment` in order to take advantage // of env-specific config files; while still having dependencies work like they // will in production (since NODE_ENV is set). // var IS_NODE_ENV_PRODUCTION = (process.env.NODE_ENV === 'production'); return _.defaults(sails.config.http.middleware || {}, { // Configure flat file server to serve static files // (By default, all explicit+shadow routes take precedence over flat files) www: (function() { var flatFileMiddleware = require('serve-static')(sails.config.paths['public'], { maxAge: sails.config.http.cache }); return flatFileMiddleware; })(), // If a Connect session store is configured, hook it up to Express session: (function() { // Silently do nothing if there's no session hook. // You can still have session middleware without the session hook enabled, // you just have to provide it yourself by configuring sails.config.http.middleware.session. if (!sails.hooks.session) { sails.log.verbose('Cannot load default HTTP session middleware when Sails session hook is disabled. Skipping...'); return; } // Complain a bit louder if the session hook is enabled, but not configured. if (!sails.config.session) { sails.log.error('Cannot load default HTTP session middleware without `sails.config.session` configured. Skipping...'); return; } var configuredSessionMiddleware = sails._privateSessionMiddleware; return function session(req, res, next){ // --• // Run the session middleware. configuredSessionMiddleware(req,res,function (err) { if (!err) { return next(); } var errMsg = 'Error occurred in session middleware :: ' + util.inspect((err&&err.stack)?err.stack:err, false, null); sails.log.error(errMsg); // If headers have already been sent (e.g. because of timing issues in application-level code), // then don't attempt to send another response. // (but still log a warning) if (res.headersSent) { sails.log.warn('The session middleware encountered an error and triggered its callback, but response headers have already been sent. Rather than attempting to send another response, failing silently...'); return; } // --• // Otherwise, we can go ahead and send a response. return res.status(400).send(errMsg); }); }; })(), // Build configured favicon mwr function. favicon: (function (){ var toServeFavicon = require('serve-favicon'); var pathToDefaultFavicon = Path.resolve(__dirname,'./default-favicon.ico'); var serveFaviconMwr = toServeFavicon(pathToDefaultFavicon); return serveFaviconMwr; })(), cookieParser: (function() { var cookieParser = sails.config.http.middleware.cookieParser; if (!cookieParser) { cookieParser = require('cookie-parser'); } var sessionSecret = sails.config.session && sails.config.session.secret; // If available, Sails uses the configured session secret for signing cookies. if (sessionSecret) { // Ensure secret is a string. This check happens in the session hook as well, // but sails.config.session.secret may still be provided even if the session hook // is turned off, so to be extra anal we'll check here as well. if (!_.isString(sessionSecret)) { throw flaverr({ name: 'userError', code: 'E_INVALID_SESSION_SECRET' }, new Error('If provided, sails.config.session.secret should be a string.')); } return cookieParser(sessionSecret); } // If no session secret was provided in config // (e.g. if session hook is disabled and config/session.js is removed) // then we do not enable signed cookies by providing a cookie secret. // (note that of course signed cookies can still be enabled in a Sails app: // see conceptual docs on disabling the session hook for info) else { return cookieParser(); } })(), compress: IS_NODE_ENV_PRODUCTION && require('compression')(), // Configures the middleware function used for parsing the HTTP request body, if enabled. bodyParser: (function() { var opts = {}; var fn; opts.onBodyParserError = function (err, req, res, next) {// eslint-disable-line no-unused-vars // Note that we _need_ all four arguments in order for this function // to have special meaning as an error handler (i.e. to Express) var bodyParserFailureErrorMsg = 'Unable to parse HTTP body- error occurred :: ' + util.inspect((err&&err.stack)?err.stack:err, false, null); sails.log.error(bodyParserFailureErrorMsg); if (IS_NODE_ENV_PRODUCTION) { return res.status(400).send(); } return res.status(400).send(bodyParserFailureErrorMsg); }; // Handle original bodyParser config: //////////////////////////////////////////////////////// // If a body parser was configured, use it if (sails.config.http.bodyParser) { fn = sails.config.http.bodyParser; return fn(opts); } else if (sails.config.http.bodyParser === false) { // Allow for explicit disabling of bodyParser using traditional // `express.bodyParser` conf return undefined; } // Default to built-in bodyParser: fn = require('skipper'); return fn(opts); })(), // Add powered-by Sails header poweredBy: function xPoweredBy(req, res, next) { res.header('X-Powered-By', 'Sails <sailsjs.com>'); next(); } }); };