sails
Version:
API-driven framework for building realtime apps, using MVC conventions (based on Express and Socket.io)
294 lines (231 loc) • 14.3 kB
JavaScript
/**
* Module dependencies.
*/
var path = require('path');
var util = require('util');
var _ = require('@sailshq/lodash');
var flaverr = require('flaverr');
var toStartServer = require('./start');
var toInitializeHttpHook = require('./initialize');
module.exports = function(sails) {
/**
* Expose `http` hook definition
*/
return {
defaults: {
// Self-awareness: the host the server *thinks it is*
// (this is necessary for some production environments-- only set it if you _absolutely_ need it)
explicitHost: undefined,
// Port to run this app on
port: 1337,
// SSL cert settings end up here
ssl: {},
// Path static files will be served from
// Uses `path.resolve()` to accept either:
// • an absolute path
// • a relative path from the app root (sails.config.appPath)
paths: {
public: '.tmp/public'
},
// New http-only middleware config
// (provides default middleware)
http: {
middleware: {
order: [
'cookieParser',
'session',
'bodyParser',
'compress',
'poweredBy',
'router',
'www',
'favicon',
],
// Built-in HTTP middleware functions are injected after the express
// app instance has been created (i.e. `app`). See `./initialize.js`
// and `./get-configured-http-middleware-fns.js` in this hook for details.
},
// HTTP cache configuration
//
// > Implicit default in production is 365.25 days (in dev: 1 milisecond).
// FUTURE: remove implicit production default, and if this is production
// and no cache was set, log a warning (in `configure`)
cache: process.env.NODE_ENV !== 'production' ? 1 : 31557600000,
// Extra options to pass directly into the Express server
// when it is instantiated
// (or false to disable)
//
// This is the options object for the `createServer` method, as discussed here:
// • http://nodejs.org/docs/v4.0.0/api/https.html#https_class_https_server
// • http://nodejs.org/docs/v6.0.0/api/https.html#https_class_https_server
// • http://nodejs.org/docs/v7.0.0/api/https.html#https_class_https_server
serverOptions: undefined,
// Custom express middleware function to use.
// (FUTURE: add deprecation message if this is attempted-- instead recommend using an arbitrary middleware)
customMiddleware: undefined,
// Should be left false unless behind a proxy.
// (this is passed in to Express as the "trust proxy" setting)
trustProxy: false,
}//< .http>
},//< / defaults >
configure: function() {
// If one piece of the ssl config is specified, ensure the other required piece is there
if (sails.config.ssl && (
sails.config.ssl.cert && !sails.config.ssl.key
) || (!sails.config.ssl.cert && sails.config.ssl.key)) {
throw flaverr({ name: 'userError', code: 'E_INVALID_SSL_CONFIG' }, new Error('Invalid SSL configuration in `sails.config.ssl`! Must include `cert` and `key` properties!'));
}
// Deprecate `customMiddlware` option.
if (sails.config.http.customMiddleware) {
sails.log.debug('Warning: use of `customMiddleware` is deprecated in Sails 1.0.');
sails.log.debug('Instead, use an Express 4-compatible middleware (res, res, next) function.');
sails.log.debug('See http://sailsjs.com/docs/upgrading/to-v-1-0#?express-4 for more info.');
sails.log.debug();
}
// Path static files will be served from
//
// Uses `path.resolve()` to accept either:
// • an absolute path
// • a relative path from the app root (sails.config.appPath)
sails.config.paths.public = path.resolve(sails.config.appPath, sails.config.paths.public);
// If no _explicit_ middleware order is specified, make sure the implicit default order
// will be used. This allows overriding built-in middleware functions (like `www`)
// without having to explicitly configure the `sails.config.http.middleware.order` array.
sails.config.http.middleware.order = sails.config.http.middleware.order || sails.hooks.http.defaults(sails.config).http.middleware.order;
// Note that this (^^) is probably not necessary anymore.
// ┌┐ ┌─┐┌─┐┬┌─┬ ┬┌─┐┬─┐┌┬┐┌─┐ ┌─┐┌─┐┌┬┐┌─┐┌─┐┌┬┐┬┌┐ ┬┬ ┬┌┬┐┬ ┬
// ├┴┐├─┤│ ├┴┐│││├─┤├┬┘ ││└─┐ │ │ ││││├─┘├─┤ │ │├┴┐││ │ │ └┬┘
// └─┘┴ ┴└─┘┴ ┴└┴┘┴ ┴┴└──┴┘└─┘ └─┘└─┘┴ ┴┴ ┴ ┴ ┴ ┴└─┘┴┴─┘┴ ┴ ┴
// ┬ ┌┬┐┌─┐┌─┐┬─┐┌─┐┌─┐┌─┐┌┬┐┬┌─┐┌┐┌ ┬ ┬┌─┐┬─┐┌┐┌┬┌┐┌┌─┐┌─┐
// ┌┼─ ││├┤ ├─┘├┬┘├┤ │ ├─┤ │ ││ ││││ │││├─┤├┬┘││││││││ ┬└─┐
// └┘ ─┴┘└─┘┴ ┴└─└─┘└─┘┴ ┴ ┴ ┴└─┘┘└┘ └┴┘┴ ┴┴└─┘└┘┴┘└┘└─┘└─┘
// Backwards compatibility and/or deprecation messages for:
// • `sails.config.host` => `sails.config.explicitHost`.
// • `sails.config.express` => `sails.config.http`.
// • `sails.config.express.loadMiddleware` => `sails.config.http`.
// • `sails.config.cache.maxAge` => `sails.config.http.cache`.
if (sails.config.host) {
sails.log.debug('The `sails.config.host` setting is deprecated in Sails 1.0.');
sails.log.debug('Please use `sails.config.explicitHost` instead.\n');
sails.config.explicitHost = sails.config.host;
}
if (sails.config.express) {
throw flaverr({ name: 'userError', code: 'E_INVALID_HTTP_CONFIG' }, new Error(
'\n-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'+
'The `sails.config.express` setting is no longer available in Sails 1.0.\n'+
'Please use `sails.config.http.js` instead (available in `config/http.js` in new apps).\n'+
'-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'
));
}
if (sails.config.http.loadMiddleware) {
throw flaverr({ name: 'userError', code: 'E_INVALID_HTTP_CONFIG' }, new Error(
'\n-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'+
'The `sails.config.http.loadMiddleware` setting is no longer available in Sails 1.0.\n'+
'Please use `sails.config.http.middleware.order` instead.\n'+
'-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'
));
}
if (sails.config.cache) {
throw flaverr({ name: 'userError', code: 'E_INVALID_HTTP_CONFIG' }, new Error(
'\n-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'+
'The `sails.config.cache` setting is no longer available in Sails 1.0.\n'+
'Please use `sails.config.http.cache` instead.\n'+
'-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'
));
}
if (sails.config.http.trustProxy === 0 || sails.config.http.trustProxy === '' || sails.config.http.trustProxy === null || _.isNaN(sails.config.http.trustProxy)) {
throw flaverr({ name: 'userError', code: 'E_HTTP_BAD_TRUSTPROXY' }, new Error(
'\n-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'+
'The `sails.config.http.trustProxy` property cannot be zero, empty string, null or NaN.\n'+
'The property is currently set to: `' + util.inspect(sails.config.http.trustProxy) + '`.\n'+
'To indicate that your app is directly facing the internet, set `trustProxy` to `false`.\n'+
'-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// BACKWARDS COMPATIBILITY:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (sails.config.http.bodyParser) {
sails.log.debug('The `sails.config.http.bodyParser` setting is deprecated in Sails 1.0.');
sails.log.debug('Please use `sails.config.http.middleware.bodyParser` instead.');
sails.log.debug('See http://sailsjs.com/docs/concepts/middleware for more details.\n');
if (!sails.config.http.middleware.bodyParser) {
sails.config.http.middleware.bodyParser = sails.config.http.bodyParser;
}
}
if (sails.config.http.methodOverride) {
sails.log.debug('The `sails.config.http.methodOverride` setting is deprecated in Sails 1.0.');
sails.log.debug('Please use `sails.config.http.middleware.methodOverride` instead.');
sails.log.debug('Also note that in Sails 1.0, the `methodOverride` module is no longer');
sails.log.debug('included by default -- you\'ll need to `npm install method-override --save`');
sails.log.debug('and add `methodOverride` to the `sails.config.http.middleware.order` array.');
sails.log.debug('See http://sailsjs.com/docs/concepts/middleware for more details.\n');
if (!sails.config.http.middleware.methodOverride) {
sails.config.http.middleware.methodOverride = sails.config.http.methodOverride;
}
}
if (sails.config.http.cookieParser) {
sails.log.debug('The `sails.config.http.cookieParser` setting is deprecated in Sails 1.0.');
sails.log.debug('Please use `sails.config.http.middleware.cookieParser` instead.');
sails.log.debug('See http://sailsjs.com/docs/concepts/middleware for more details.\n');
if (!sails.config.http.middleware.cookieParser) {
sails.config.http.middleware.cookieParser = sails.config.http.cookieParser;
}
}
// ┬ ┬┌─┐┬─┐┬┌─┐┬ ┬ ┌┬┐┬┌┬┐┌┬┐┬ ┌─┐┬ ┬┌─┐┬─┐┌─┐
// └┐┌┘├┤ ├┬┘│├┤ └┬┘ ││││ ││ │││ ├┤ │││├─┤├┬┘├┤
// └┘ └─┘┴└─┴└ ┴ ┴ ┴┴─┴┘─┴┘┴─┘└─┘└┴┘┴ ┴┴└─└─┘
// Make sure that middleware in the order exists, and that every
// custom middleware is present in the order.
// Loop through all of the middleware in `sails.config.http.middleware`, and verify that it's
// in the order (skipping the `order` key itself).
_.each(_.without(_.keys(sails.config.http.middleware), 'order'), function (middlewareName) {
// If the custom middleware isn't in the middleware order, bail.
// Make an exception for 404, 500 and startRequest timer, which we'll handle more
// gently when initializing the hook.
if (!_.contains(sails.config.http.middleware.order.concat(['404', '500', 'startRequestTimer']), middlewareName)) {
throw flaverr({ name: 'userError', code: 'E_INVALID_HTTP_CONFIG' }, new Error(
'\n-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'+
'Detected a custom middleware `' + middlewareName + '` that does not appear in the\n'+
'middleware order. Please add `' + middlewareName + '` to `sails.config.http.middleware.order`.\n'+
'See http://sailsjs.com/docs/concepts/middleware for more info.\n'+
'-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'
));
}
});
// Now loop through all of the middleware names in `sails.config.http.middleware.order` (ignoring
// the built-in ones) and verify that there's a matching custom middleware.
// Make an exception for the middleware that was removed from the order in Sails 1.0, which we'll
// handle more gently when initializing the hook.
_.each(_.difference(sails.config.http.middleware.order, sails.hooks.http.defaults.http.middleware.order.concat(['404', '500', 'startRequestTimer', 'handleBodyParserError', 'methodOverride', '$custom'])), function(middlewareName) {
if (!_.isFunction(sails.config.http.middleware[middlewareName])) {
throw flaverr({ name: 'userError', code: 'E_INVALID_HTTP_CONFIG' }, new Error(
'\n-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'+
'Detected an entry for `' + middlewareName + '` in `sails.config.http.middleware.order`,\n'+
'but `sails.config.http.middleware[\'' + middlewareName + '\']` is undefined or not a function.\n'+
'Please provide a custom `req, res, next` middleware function for `' + middlewareName + '`,\n'+
'or remove it from the order. See http://sailsjs.com/docs/concepts/middleware for more info.\n'+
'-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n'
));
}
});
},
/**
* Initialize is fired first thing when the hook is loaded
* but after waiting for user config (if applicable).
*/
initialize: toInitializeHttpHook(sails),
/**
* `handleLift` is fired when sails is ready for HTTP requests to
* start coming in.
*
* @param {Function} done
*/
handleLift: function(done){
// In order for `sails.config` to be correct, this needs to happen in here.
var startServer = toStartServer(sails);
// Now that Sails is ready, start listening for requests on
// the express server.
startServer(done);
}
};
};