不知道express里面有没有类似restify中queryParser的中间件,效果就是所有传过来的参数不管是路由里面的、get、post的都会再req.params里面。
自己写一个,应该不会超过3行
@i5ting 三行写了一下:
App.use ( req, res, next )-> _.extend req.params, req.body, req.query next()
但是发现了一个问题:req.params在当前中间件修改生效了, 但是在下一个中间就被重置了。我测试了一下给req添加一个key例如req.test='test’是能够被传递到下一个中间件的。请指正。
@showen 这句放的位置有关系的
@i5ting 确定放到了最前面,而且刚才在它之后写了一个中间件测试了是传不过来的。
@showen 不对,是在解析之后,也就是路由前面
@i5ting 大哥你测试了没 我连续写两个中间件req.params修改值都没有传给下一个中间件
上面的讨论可能版本不同? 以下仅供参考
app.use(function(req, res, next){ Object.defineProperty(req, 'params', { set: function(val){ this._allParams = _.extend(val, req.query, req.body); }, get: function(){ return this._allParams; } }); next(); });
@showen 代码发出来看看?我光看你的描述的话,得出的结论跟 @i5ting 一样
@William17 赞 你这种能生效 我用的node版本是4.2.2的 express是4.13.1 是版本的问题吗 能不能详细解释一下呢 还有就是发现一个小问题 在Object.defineProperty之后打印req.params是undefined 但是在Object.defineProperty之前打印就是一个空Object:{} 很诧异
Object.defineProperty
Object:{}
@alsotang 就上面三行代码 问题现在可以简单描述为:上一个中间件修改了req.params在下一个中间件不生效 @William17 给的解决方案能生效
@William17 我看了restify的queryParser源码也是直接修改的req.params如下:
function queryParser(options) { if (!options) options = {}; assert.object(options, 'options'); function parseQueryString(req, res, next) { if (!req.getQuery()) { req.query = {}; return (next()); } req._query = req.query = qs.parse(req.getQuery()); if (options.mapParams !== false) { Object.keys(req.query).forEach(function (k) { if (req.params[k] && !options.overrideParams) return (false); req.params[k] = req.query[k]; return (true); }); } return (next()); } return (parseQueryString); }
@showen
我只是稍微看了express当前最新的部分代码,其它版本没看过,所以不太清楚以前的版本是不是可以直接修改req.params 对于当前最新的代码,我解释一下 /lib/router/index.js#L135
req.params
proto.handle = function handle(req, res, out) { // ... // 每进入一个Router,保存上一级Router的params // 这个parentParams在下面用来的mergeParams // 主要用于类似下面这种情况 // var router1 = require('express').Router(); // var router2 = require('express').Router({mergeParams:true}); // router1.use('/api/:version',router2); // router2.get('/user/:id',function(req, res, next){ // // 这里会有上一级Router的param // console.log(req.params.version); // }) var parentParams = req.params; // ... next(); function next(err) { // ... // 遍历这个Router的layer while (match !== true && idx < stack.length) { layer = stack[idx++]; // ... // 创建新的req.params // 如果有mergeParams=true,则把父级的params合并进来 req.params = self.mergeParams ? mergeParams(layer.params, parentParams) : layer.params; // ... } }
可以看到,每一个layer, req.params都会指向新的对象,所以在如果在某个layer修改了req.params所引用的对象的属性,这种改变不会影响到其它的layer。 因此,我们在req上动手脚。
layer
req
在Object.defineProperty之后打印req.params是undefined 但是在Object.defineProperty之前打印就是一个空Object:{}
之前是{}是因为express一开始给它赋的值,之后是undefined是因为这时候返回的值是我们getter函数里返回的req._allParams, 而这个我们没初始化定义
{}
express
undefined
req._allParams
所以,初始化一下就好了
app.use(function(req, res, next){ // 初始化 req._allParams = req.params; Object.defineProperty(req, 'params', { set: function(val){ this._allParams = _.extend(val, req.query, req.body); }, get: function(){ return this._allParams; } }); next(); });
@showen @William17 @i5ting 这种情况下,我建议还是不要覆盖 req.params 了。换个名字,req._params 之类的。
@William17 不甚感激!
@alsotang 为了兼容别人的代码。。。
CNode 社区为国内最专业的 Node.js 开源技术社区,致力于 Node.js 的技术研究。
自己写一个,应该不会超过3行
@i5ting 三行写了一下:
但是发现了一个问题:req.params在当前中间件修改生效了, 但是在下一个中间就被重置了。我测试了一下给req添加一个key例如req.test='test’是能够被传递到下一个中间件的。请指正。
@showen 这句放的位置有关系的
@i5ting 确定放到了最前面,而且刚才在它之后写了一个中间件测试了是传不过来的。
@showen 不对,是在解析之后,也就是路由前面
@i5ting 大哥你测试了没 我连续写两个中间件req.params修改值都没有传给下一个中间件
上面的讨论可能版本不同?
以下仅供参考
@showen 代码发出来看看?我光看你的描述的话,得出的结论跟 @i5ting 一样
@William17 赞 你这种能生效 我用的node版本是4.2.2的 express是4.13.1 是版本的问题吗 能不能详细解释一下呢 还有就是发现一个小问题 在
Object.defineProperty之后打印req.params是undefined 但是在Object.defineProperty之前打印就是一个空Object:{}很诧异@alsotang 就上面三行代码 问题现在可以简单描述为:上一个中间件修改了req.params在下一个中间件不生效 @William17 给的解决方案能生效
@William17 我看了restify的queryParser源码也是直接修改的req.params如下:
@showen
A
我只是稍微看了express当前最新的部分代码,其它版本没看过,所以不太清楚以前的版本是不是可以直接修改
req.params对于当前最新的代码,我解释一下
/lib/router/index.js#L135
可以看到,每一个
layer,req.params都会指向新的对象,所以在如果在某个layer修改了req.params所引用的对象的属性,这种改变不会影响到其它的layer。 因此,我们在req上动手脚。B
之前是
{}是因为express一开始给它赋的值,之后是undefined是因为这时候返回的值是我们getter函数里返回的req._allParams, 而这个我们没初始化定义所以,初始化一下就好了
@showen @William17 @i5ting 这种情况下,我建议还是不要覆盖 req.params 了。换个名字,req._params 之类的。
@William17 不甚感激!
@alsotang 为了兼容别人的代码。。。