sails
Version:
API-driven framework for building realtime apps, using MVC conventions (based on Express and Socket.io)
95 lines (81 loc) • 3.68 kB
JavaScript
/**
* Module dependencies
*/
var util = require('util');
var _ = require('@sailshq/lodash');
var detectVerb = require('../util/detect-verb');
/**
* getRouteFor()
*
* Look up more information about the first explicit route defined in this app
* which has the given route target.
*
* Note that this function _only searches explicit routes_ which have been configured
* manually (e.g. in `config/routes.js`). For more info, see:
* https://github.com/balderdashy/sails/issues/3402#issuecomment-171633341
*
* @this {SailsApp}
* ----------------------------------------------------------------------------------------
*
* Usage:
*
* ```
* getRouteFor('DuckController.quack');
* getRouteFor({ target: 'DuckController.quack' });
* // =>
* // {
* // url: '/ducks/:id/quack',
* // method: 'post'
* // }
* ```
*/
module.exports = function getRouteFor(routeQuery){
// Get reference to sails app instance.
var sails = this;
// Get the identity of the action we're trying to look up, based on the route we're querying.
var actionToLookup;
try {
actionToLookup = sails.router.getActionIdentityForTarget(routeQuery);
} catch (unusedErr) { // FUTURE: provide access to error details instead of swallowing
var invalidUsageErr = new Error(`Usage error: sails.getRouteFor() expects a string route target (e.g. "DuckController.quack") or a dictionary with either a "target" (e.g. {target: "DuckController.quack"}) or an "action" (e.g. {controller: "duck", action: "quack"} or {action: "duck/quack"}). But instead, it received a ${typeof routeQuery}: ${util.inspect(routeQuery, {depth: null})}`);
invalidUsageErr.code = 'E_USAGE';
throw invalidUsageErr;
}
// Now look up the first route with this target (`routeTargetToLookup`).
var firstMatchingRouteAddress = _.find(_.keys(sails.router.explicitRoutes), function (address) {
var target = sails.router.explicitRoutes[address];
// Attempt to look up the action that corresponds to this route target.
var actionIdentity;
try {
actionIdentity = sails.router.getActionIdentityForTarget(target);
} catch (e) {
// If the target is not an action (i.e if it is a view, a raw req/res function or something else)
// then just return false (it's not a match for the action we're looking up).
if (e.code === 'E_NOT_ACTION_TARGET') {
return false;
}
// If some other error occurred looking up the target, then throw it.
throw e;
}
// Ok, we got an action identity. Does it match the identity of the action we're trying to look up?
return (actionIdentity === actionToLookup);
});
// If no route was found, throw an error.
if (!firstMatchingRouteAddress) {
var unrecognizedTargetErr = new Error('Route not found: No explicit route could be found in this app with the specified target (`'+util.inspect(routeQuery, {depth: null})+'`).');
unrecognizedTargetErr.code = 'E_NOT_FOUND';
throw unrecognizedTargetErr;
}
// Now that the raw route address been located, we'll normalize it:
//
// If route address is '*', it will be automatically corrected to `/*` when bound, so also reflect that here.
firstMatchingRouteAddress = firstMatchingRouteAddress === '*' ? '/*' : firstMatchingRouteAddress;
// Then we parse it into its HTTP method and URL pattern parts.
var parsedAddress = detectVerb(firstMatchingRouteAddress);
// At this point we being building the final return value- the route info dictionary.
var routeInfo = {};
routeInfo.method = parsedAddress.verb || '';
routeInfo.url = parsedAddress.path;
// And finally return the route info.
return routeInfo;
};