UNPKG

sails

Version:

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

116 lines (86 loc) 5.15 kB
module.exports = function(sails) { /** * Module dependencies. */ var _ = require('@sailshq/lodash'); var setHeaders = require('./set-headers'); var setPreflightConfig = require('./set-preflight-config'); var detectVerb = require('../../../util/detect-verb'); /** * Expose hook definition */ return function initializeCors() { // Once it's time to bind shadow routes, get to bindin'. sails.on('router:before', function () { // (FUTURE: consider changing this ^^ to `sails.after()` for consistency) // If we're setting CORS on all routes by default, set up a universal route for it here. // CORS can still be turned off for specific routes by setting `cors:false` if (sails.config.security.cors.allRoutes === true) { sails.router.bind('/*', setHeaders(sails.config.security.cors), 'all', {_middlewareType: 'CORS HOOK: sendHeaders'}); } // Otherwise, default to blocking all cross-origin requests. else { sails.router.bind('/*', setHeaders({allowOrigins: false}), null, {_middlewareType: 'CORS HOOK: clearHeaders'}); } // Declare a var to hold the various CORS settings for preflight OPTIONS routes, which we'll build up // as we look at the route configs below. var optionsRouteConfigs = {}; // Loop through all configured routes, looking for CORS options _.each(sails.router.explicitRoutes, function(routeConfig, route) { // Get some info about the route, like its path and verb. var routeInfo = detectVerb(route); var path = routeInfo.original.toLowerCase(); var verb = routeInfo.verb.toLowerCase(); // Get a handle to the route CORS config. var routeCorsConfig = routeConfig.cors; // If this route doesn't have its own CORS config, move on. if (_.isUndefined(routeCorsConfig)) { return; } // If this route is pointing to the CSRF token route, log a warning. if (routeCorsConfig !== false && routeConfig.action === 'security/grant-csrf-token') { sails.log.verbose('The `grant-csrf-token` action is not supported for cross-origin requests in situations/browsers where 3rd party cookies are blocked.'); sails.log.verbose('(You are seeing this message because the route `' + verb + ' ' + path + '` has CORS settings configured.)'); } optionsRouteConfigs[path] = optionsRouteConfigs[path] || {}; // If cors is set to `true`, and we're not doing all routes by default, set // the CORS headers for this route using the default origin if (routeCorsConfig === true) { if (!sails.config.security.cors.allRoutes) { // Use the default CORS config for this path on an OPTIONS request optionsRouteConfigs[path][verb || 'default'] = sails.config.security.cors; sails.router.bind(route, setHeaders(sails.config.security.cors), null, {_middlewareType: 'CORS HOOK: setHeaders'}); } } // If cors is set to `false`, clear the CORS headers for this route else if (routeCorsConfig === false) { // Clear headers on an OPTIONS request for this path optionsRouteConfigs[path][verb || 'default'] = 'clear'; sails.router.bind(route, setHeaders({allowOrigins: false}), 'all', {_middlewareType: 'CORS HOOK: clearHeaders'}); return; } // Else if cors is set to a string, use that has the origin else if (typeof routeCorsConfig === 'string') { optionsRouteConfigs[path][verb || 'default'] = _.extend({allowOrigins: [routeCorsConfig]}); sails.router.bind(route, setHeaders(_.extend({}, sails.config.security.cors, {allowOrigins: [routeCorsConfig], methods: verb})), null, {_middlewareType: 'CORS HOOK: setHeaders'}); } // Else if cors is an object, use that as the config else if (_.isPlainObject(routeCorsConfig)) { // Set configuration for the preflight OPTIONS request for this route. optionsRouteConfigs[path][verb || 'default'] = routeCorsConfig; // Bind a route that will set CORS headers for this url/path combo. sails.router.bind(route, setHeaders(_.extend({}, routeCorsConfig)), null, {_middlewareType: 'CORS HOOK: setHeaders'}); } // Otherwise we don't recognize the CORS config, so throw a warning else { sails.log.warn('Invalid CORS settings for route '+route); } }); // Now that we have `optionsRouteConfigs`, a list of all of the routes that (possibly) need // to be preflighted, construct a route that will handle OPTIONS requests for all of those routes. // Sending the result of `setPreflightConfig` (a function) into `setHeaders` will cause `setHeaders` // to run the function in order to determine the CORS options to use. sails.router.bind('options /*', setHeaders(setPreflightConfig(optionsRouteConfigs, sails.config.security.cors)), 'options', {_middlewareType: 'CORS HOOK: preflight'}); }); // Continue loading this Sails app. return; }; };