2015-10-01 00:30:16 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Module dependencies
|
|
|
|
*/
|
|
|
|
|
2015-11-10 16:29:34 +01:00
|
|
|
// Node.js core.
|
|
|
|
const cluster = require('cluster');
|
|
|
|
|
2015-10-01 00:30:16 +02:00
|
|
|
// Public node modules.
|
|
|
|
const _ = require('lodash');
|
|
|
|
|
|
|
|
// Local utilities.
|
|
|
|
const regex = require('../../../../util/regex');
|
2016-01-26 18:03:52 +01:00
|
|
|
const JSONAPI = require('../jsonapi')();
|
2016-03-11 14:11:05 +01:00
|
|
|
const responsesPolicy = require('../responses/policies/responses');
|
2015-10-01 00:30:16 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Router hook
|
|
|
|
*/
|
|
|
|
|
|
|
|
module.exports = function (strapi) {
|
|
|
|
const hook = {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Default options
|
|
|
|
*/
|
|
|
|
|
|
|
|
defaults: {
|
|
|
|
prefix: '',
|
2016-02-24 16:33:42 +01:00
|
|
|
routes: {},
|
|
|
|
graphql: {
|
|
|
|
enabled: true,
|
2016-03-09 16:13:19 +01:00
|
|
|
route: '/graphql',
|
|
|
|
graphiql: false,
|
|
|
|
pretty: true
|
2016-02-24 16:33:42 +01:00
|
|
|
}
|
2015-10-01 00:30:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize the hook
|
|
|
|
*/
|
|
|
|
|
|
|
|
initialize: function (cb) {
|
|
|
|
|
|
|
|
// Middleware used for every routes.
|
|
|
|
// Expose the endpoint in `this`.
|
2015-11-09 19:05:33 +01:00
|
|
|
function globalPolicy(endpoint, value, route) {
|
2015-10-01 00:30:16 +02:00
|
|
|
return function * (next) {
|
|
|
|
this.request.route = {
|
2015-11-09 19:05:33 +01:00
|
|
|
endpoint: _.trim(endpoint),
|
|
|
|
controller: _.trim(value.controller),
|
|
|
|
action: _.trim(value.action),
|
|
|
|
splittedEndpoint: _.trim(route.endpoint),
|
|
|
|
verb: route.verb && _.trim(route.verb.toLowerCase())
|
2015-10-01 00:30:16 +02:00
|
|
|
};
|
|
|
|
yield next;
|
2015-10-05 18:29:04 +02:00
|
|
|
};
|
2015-10-01 00:30:16 +02:00
|
|
|
}
|
|
|
|
|
2015-11-13 17:45:47 +01:00
|
|
|
if (((cluster.isWorker && strapi.config.reload.workers > 0) || (cluster.isMaster && strapi.config.reload.workers < 1)) || (!strapi.config.reload && cluster.isMaster)) {
|
2015-11-10 16:29:34 +01:00
|
|
|
let route;
|
|
|
|
let controller;
|
|
|
|
let action;
|
|
|
|
let policies = [];
|
|
|
|
|
2016-03-11 14:11:05 +01:00
|
|
|
// Add the `responsesPolicy` to the list of policies.
|
|
|
|
if (strapi.config.responses) {
|
|
|
|
strapi.policies.responsesPolicy = responsesPolicy;
|
|
|
|
}
|
|
|
|
|
2015-11-10 16:29:34 +01:00
|
|
|
// Initialize the router.
|
|
|
|
if (!strapi.router) {
|
|
|
|
strapi.router = strapi.middlewares.router({
|
|
|
|
prefix: strapi.config.prefix
|
|
|
|
});
|
|
|
|
}
|
2015-10-30 14:36:19 +01:00
|
|
|
|
2015-11-10 16:29:34 +01:00
|
|
|
// Parse each route from the user config, load policies if any
|
|
|
|
// and match the controller and action to the desired endpoint.
|
|
|
|
_.forEach(strapi.config.routes, function (value, endpoint) {
|
|
|
|
try {
|
|
|
|
route = regex.detectRoute(endpoint);
|
|
|
|
|
|
|
|
// Check if the controller is a function.
|
|
|
|
if (typeof value.controller === 'function') {
|
|
|
|
action = value.controller;
|
|
|
|
} else {
|
|
|
|
controller = strapi.controllers[value.controller.toLowerCase()];
|
|
|
|
action = controller[value.action];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init policies array.
|
|
|
|
policies = [];
|
|
|
|
|
|
|
|
// Add the `globalPolicy`.
|
2015-11-10 17:28:44 +01:00
|
|
|
policies.push(globalPolicy(endpoint, value, route));
|
2016-01-29 16:01:10 +01:00
|
|
|
|
2016-03-11 14:11:05 +01:00
|
|
|
// Add the `responsesPolicy`.
|
|
|
|
if (strapi.config.responses) {
|
|
|
|
policies.push(responsesPolicy);
|
|
|
|
}
|
|
|
|
|
2016-01-29 16:01:10 +01:00
|
|
|
// Enabled JSON API support
|
|
|
|
if ((_.isPlainObject(strapi.config.jsonapi) && strapi.config.jsonapi.enabled === true) || (_.isBoolean(strapi.config.jsonapi) && strapi.config.jsonapi === true)) {
|
|
|
|
policies.push(JSONAPI.parse(strapi));
|
|
|
|
}
|
2015-11-10 16:29:34 +01:00
|
|
|
|
|
|
|
if (_.isArray(value.policies) && !_.isEmpty(value.policies)) {
|
|
|
|
_.forEach(value.policies, function (policy) {
|
|
|
|
if (strapi.policies[policy]) {
|
|
|
|
policies.push(strapi.policies[policy]);
|
|
|
|
} else {
|
|
|
|
strapi.log.error('Ignored attempt to bind route `' + endpoint + '` with unknown policy `' + policy + '`.');
|
|
|
|
process.exit(1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
strapi.router[route.verb.toLowerCase()](route.endpoint, strapi.middlewares.compose(policies), action);
|
|
|
|
} catch (err) {
|
|
|
|
strapi.log.warn('Ignored attempt to bind route `' + endpoint + '` to unknown controller/action.');
|
2015-10-01 00:30:16 +02:00
|
|
|
}
|
2015-11-10 16:29:34 +01:00
|
|
|
});
|
2015-10-22 17:54:43 +02:00
|
|
|
|
2016-02-24 16:33:42 +01:00
|
|
|
// Override default configuration for GraphQL
|
|
|
|
_.assign(this.defaults.graphql, strapi.config.graphql);
|
|
|
|
|
2016-02-23 19:01:22 +01:00
|
|
|
// Define GraphQL route to GraphQL schema
|
|
|
|
// or disable the global variable
|
2016-02-24 16:33:42 +01:00
|
|
|
if (this.defaults.graphql.enabled === true) {
|
2016-03-02 17:53:07 +01:00
|
|
|
strapi.app.use(strapi.middlewares.mount(this.defaults.graphql.route, strapi.middlewares.graphql((request, context) => ({
|
2016-02-24 16:33:42 +01:00
|
|
|
schema: strapi.schemas,
|
2016-03-09 16:13:19 +01:00
|
|
|
pretty: this.defaults.graphql.pretty,
|
2016-03-02 17:53:07 +01:00
|
|
|
rootValue: {
|
|
|
|
context: context
|
2016-03-09 16:13:19 +01:00
|
|
|
},
|
|
|
|
graphiql: this.defaults.graphql.graphiql
|
2016-03-02 17:53:07 +01:00
|
|
|
}))));
|
2016-02-23 19:01:22 +01:00
|
|
|
} else {
|
|
|
|
global.graphql = undefined;
|
|
|
|
}
|
|
|
|
|
2015-11-10 16:29:34 +01:00
|
|
|
// Let the router use our routes and allowed methods.
|
|
|
|
strapi.app.use(strapi.router.routes());
|
|
|
|
strapi.app.use(strapi.router.allowedMethods());
|
|
|
|
|
|
|
|
// Handle router errors.
|
|
|
|
strapi.app.use(function * (next) {
|
|
|
|
try {
|
|
|
|
yield next;
|
|
|
|
const status = this.status || 404;
|
|
|
|
if (status === 404) {
|
|
|
|
this.throw(404);
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
err.status = err.status || 500;
|
|
|
|
err.message = err.expose ? err.message : 'Houston, we have a problem.';
|
|
|
|
|
|
|
|
this.status = err.status;
|
|
|
|
this.body = {
|
|
|
|
code: err.status,
|
|
|
|
message: err.message
|
|
|
|
};
|
|
|
|
|
|
|
|
this.app.emit('error', err, this);
|
2015-10-01 00:30:16 +02:00
|
|
|
}
|
2015-11-10 16:29:34 +01:00
|
|
|
});
|
2015-10-13 23:41:22 +02:00
|
|
|
}
|
2015-10-13 23:33:17 +02:00
|
|
|
|
2015-10-01 00:30:16 +02:00
|
|
|
cb();
|
2015-11-09 15:10:53 +01:00
|
|
|
},
|
2015-10-01 00:30:16 +02:00
|
|
|
|
2015-11-09 15:10:53 +01:00
|
|
|
/**
|
|
|
|
* Reload the hook
|
|
|
|
*/
|
|
|
|
|
|
|
|
reload: function () {
|
2015-11-10 16:29:34 +01:00
|
|
|
delete strapi.router;
|
2015-10-01 00:30:16 +02:00
|
|
|
|
2015-11-09 15:10:53 +01:00
|
|
|
hook.initialize(function (err) {
|
|
|
|
if (err) {
|
|
|
|
strapi.log.error('Failed to reinitialize the router.');
|
|
|
|
strapi.stop();
|
|
|
|
} else {
|
|
|
|
strapi.emit('hook:router:reloaded');
|
2015-10-01 00:30:16 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return hook;
|
|
|
|
};
|