Use generators, send strapi instance in parser and optimizations

This commit is contained in:
Aurélien Georget 2016-01-27 16:45:44 +01:00
parent fad6c2af6d
commit c7049253d6
3 changed files with 91 additions and 61 deletions

View File

@ -19,17 +19,16 @@ module.exports = {
* Parse request
*/
parse: function (ctx, cb) {
parse: function * (ctx, cb) {
switch (ctx.method.toUpperCase()) {
case 'GET':
console.log('GET');
break;
case 'PUT':
case 'POST':
this.fetchSchema(ctx, function (err) {
cb(err);
yield this.fetchSchema(ctx, function * (err) {
yield cb(err);
});
console.log('POST|PUT');
break;
case 'DELETE':
console.log('DELETE');
@ -42,40 +41,56 @@ module.exports = {
* Fetch attributes schema
*/
fetchSchema : function (ctx, cb) {
fetchSchema: function * (ctx, cb) {
const attributes = ctx.request.body;
if (!attributes.hasOwnProperty('data')) {
ctx.response.status = 404;
ctx.response.body = 'Missing `data` member';
return yield cb({
status: 403,
body: 'Missing `data` member'
});
} else if (!attributes.data.hasOwnProperty('type')) {
ctx.response.status = 404;
ctx.response.body = 'Missing `type` member';
return yield cb({
status: 403,
body: 'Missing `type` member'
});
} else if (!strapi.models.hasOwnProperty(attributes.data.type)) {
ctx.response.status = 404;
ctx.response.body = 'Unknow `type` ' + attributes.data.type;
} else {
// Extract required attributes
const requiredAttributes = _.filter(strapi.models[attributes.data.type].attributes, {required:true});
// Identify required relationships
const relationships = _.indexBy(strapi.models[attributes.data.type].associations, 'alias');
// Extract required relationships
const requiredRelationships = _.intersection(_.keys(requiredAttributes), _.keys(relationships));
console.log(requiredAttributes);
console.log(requiredRelationships);
if (_.size(requiredAttributes) > 0 && _.isEmpty(attributes.data.attributes)) {
ctx.response.status = 404;
ctx.response.body = 'Missing required attributes';
} else if (!_.isEmpty(_.difference(_.keys(requiredRelationships), _.keys(attributes.data.relationships)))) {
ctx.response.status = 404;
ctx.response.body = 'Missing required relationships';
} else {
cb();
console.log("coucou");
// Looks good
}
return yield cb({
status: 403,
body: 'Unknow `type` ' + attributes.data.type
});
}
// Extract required attributes
const requiredAttributes = _.omit(_.mapValues(strapi.models[attributes.data.type].attributes, function (attr) {
return attr.required ? attr : undefined;
}), _.isUndefined);
// Identify missing attributes
const missingAttributes = _.difference(_.keys(requiredAttributes), _.keys(attributes.data.attributes));
if (!_.isEmpty(missingAttributes)) {
return yield cb({
status: 403,
body: 'Missing required attributes (' + missingAttributes.toString() + ')'
});
}
// Identify required relationships
const relationships = _.indexBy(strapi.models[attributes.data.type].associations, 'alias');
// Extract required relationships
const requiredRelationships = _.intersection(_.keys(requiredAttributes), _.keys(relationships));
// Identify missing relationships
const missingRelationships = _.difference(_.keys(requiredRelationships), _.keys(attributes.data.relationships));
if (!_.isEmpty(missingRelationships)) {
return yield cb({
status: 403,
body: 'Missing required relationships (' + missingRelationships.toString() + ')'
});
}
// Looks good
yield cb();
}
};

View File

@ -39,26 +39,29 @@ module.exports = function (strapi) {
// Wait for downstream middleware/handlers to execute to build the response
yield next;
// Verify Content-Type header
if (this.request.type !== 'application/vnd.api+json') {
this.status = 406;
this.body = '';
} else if (this.request.method === 'GET') {
// Intercept only GET request
// Exclude administration routes
if (!strapi.api.admin.config.routes.hasOwnProperty(this.request.method + ' ' + this.request.url)) {
// Verify Content-Type header
if (this.request.type !== 'application/vnd.api+json') {
this.status = 406;
this.body = '';
} else if (this.request.method === 'GET') {
// Intercept only GET request
// Detect route
const matchedRoute = _.find(strapi.router.stack, function (stack) {
if (new RegExp(stack.regexp).test(self.request.url) && _.includes(stack.methods, self.request.method.toUpperCase())) {
return stack;
}
});
// Detect route
const matchedRoute = _.find(strapi.router.stack, function (stack) {
if (new RegExp(stack.regexp).test(self.request.url) && _.includes(stack.methods, self.request.method.toUpperCase())) {
return stack;
}
});
// Handlers set the response body
if (!_.isUndefined(matchedRoute)) {
const actionRoute = strapi.config.routes[self.request.method.toUpperCase() + ' ' + matchedRoute.path];
// Handlers set the response body
if (!_.isUndefined(matchedRoute)) {
const actionRoute = strapi.config.routes[self.request.method.toUpperCase() + ' ' + matchedRoute.path];
if (!_.isUndefined(actionRoute)) {
response.set(this, matchedRoute, actionRoute);
if (!_.isUndefined(actionRoute)) {
response.set(this, matchedRoute, actionRoute);
}
}
}
}
@ -69,17 +72,29 @@ module.exports = function (strapi) {
cb();
},
parse: function * (next) {
// Verify Content-Type header
if (this.request.type !== 'application/vnd.api+json') {
this.response.status = 406;
this.response.body = '';
} else {
request.parse(this, function * (err) {
if (!err) {
/**
* Parse request and attributes
*/
parse: function (strapi) {
return function * (next) {
const self = this;
// Verify Content-Type header and exclude administration routes
if (strapi.api.admin.config.routes.hasOwnProperty(this.request.method + ' ' + this.request.url)) {
yield next;
} else if (this.request.type !== 'application/vnd.api+json') {
this.response.status = 406;
this.response.body = '';
} else {
yield request.parse(this, function * (err) {
if (err) {
return _.assign(self.response, err);
}
yield next;
}
});
});
}
}
}
};

View File

@ -87,7 +87,7 @@ module.exports = function (strapi) {
// Add the `globalPolicy`.
policies.push(globalPolicy(endpoint, value, route));
policies.push(JSONAPI.parse);
policies.push(JSONAPI.parse(strapi));
if (_.isArray(value.policies) && !_.isEmpty(value.policies)) {
_.forEach(value.policies, function (policy) {