我使用带有Blueprint API的sails进行RESTful处理我遇到了一个简单的GET请求问题。以下面的模型为例。我们称之为Project
:
module.exports = {
attributes: {
id: {
type: 'string',
unique: true
},
name: {
type: 'string'
},
displayName: {
type: 'string'
},
...
};
由于我已定义ProjectController.js
,因此蓝图在GET /project
为我设置路线。如果我向此URL发出请求,我会获得此模型的所有未经过滤的结果,这是正确的。还有limit
,sort
等其他参数可以使用,例如GET /project?limit=5
,我仍然可以获得所有结果(假设我没有超过limit
5)。
问题在于我提供的查询参数不是为GET /project?foo
等API保留的。现在,它使用此参数作为过滤条件(sails.config.models.schema = true
),我得不到任何结果。
我的模型设置为attributes
,因此只会填充GET /project?foo
中定义的字段,因为我不希望存储垃圾信息。看到我如何为模型指定遵循模式,我理想地希望它也忽略未定义为属性的过滤条件。基本上,foo
应返回所有结果,因为VB6
不是有效属性。
这样做的主要原因是每个请求都有一个缓存破坏者参数,并且Sails将其解释为过滤器参数,从而扭曲了我的结果。
思想?
答案 0 :(得分:0)
在回应M U的后续评论时,这里的想法是通用的,而不是模型或控制器特有的。我研究了使用策略的想法,但后来我需要定义要在每个控制器上使用的策略,这仍然不允许根据具体情况对params进行更具体的过滤。
这里的最终目标是不必在我的控制器中定义任何方法,因为Blueprints隐式处理它们(例如。GET project/
会自动使用Blueprints find()
方法。不幸的是我无法完全获得不必定义我自己的ProjectController.find()
方法,但它似乎很合理,因为我仍然可以在一行中调用Blueprints中间件。
这是一个示例实用程序模块,用于从请求的不同范围(query
,body
和params
)中删除params。希望这些评论能够说明一切:
<强> requestUtils.js 强>
var _ = require('lodash');
module.exports = {
sanitizeRequestParams: function (req, scope, opts) {
var scopes = ['query', 'body', 'params'],
// global params to strip, keep and convert. Additional configurations can be supplied
// in the `opts` argument
stripParams = ['_dc'],
keepParams = [],
convertParams = {
/**
* Convert the `page` param into a calculated `skip` param for ORM
*
* The client-side framework will include the following for model
* requests:
* ?_dc=XXX&limit=XX&page=XX&start=XX
*
* The only one ORM will not use for filter criteria is `limit`. So
* instead of using `page`, we will calculate the number of records
* to skip from the `page` and `limit` params and set that to the
* request instead.
*
* @param param The request param to be converted
* @param val The value of th =e request param
* @param req The Request object
* @returns {{skip: *}}
*/
'page': function (param, val, req) {
var limit = _.toInteger(req.query.limit);
if (!_.isInteger(limit)) {
limit = sails.config.blueprints.defaultLimit;
}
return {'skip': _.max([(_.toInteger(val) * limit) - limit, 0])};
}
};
// default to all if invalid scope specified
if (scopes.indexOf(scope) < 0) {
scope = 'all';
}
opts = opts || {};
// merge in user-provided configs with the defaults
stripParams = _.concat(stripParams, opts.strip || []);
keepParams = _.concat(keepParams, opts.keep || []);
convertParams = _.merge(convertParams, opts.convert || []);
// iterate over each of the scopes to process the params
_.forEach(scopes, function (currScope) {
if (scope === currScope || scope === 'all') {
// strip the defined params from the request, optionally
// keeping the ones marked as such
_.forEach(stripParams, function (param) {
if (keepParams.indexOf(param) < 0) {
// eg: deletes `request.query._dc`
delete req[currScope][param];
}
});
// iterate the params to be converted to a new param
_.forEach(convertParams, function (fn, param) {
var newParam;
// ensure the orig param exists before writing a new one
if (req[currScope][param]) {
newParam = fn(param, req[currScope][param], req);
// eg: deletes `request.query.page`
// adds `request.query.skip` with a calculated value
delete req[currScope][param];
_.merge(req[currScope], newParam);
}
});
}
});
}
};
<强> ProjectController.js 强>
module.exports = {
find: function (req, res) {
// before: ?_dc=XXXXX&page=XX&limit=XX&start=XX
// after: ?limit=XX&skip=XX
util.sanitizeRequestParams(req, 'query', {strip: ['start']});
// let Blueprints handle the `find` method like we never existed
return sails.hooks.blueprints.middleware.find(req, res);
}
};
可能有一种更清晰的方法来处理这种问题,例如生命周期回调或钩子。到目前为止我还没有使用Sails和Node,所以它对我来说仍然是绿色的。任何反馈都表示赞赏。