问题来源
最近碰到一个很奇怪的问题,js进行网络请求的时候,只要带上+
符号,nodejs(express框架)中的req.query.key
的值里面的+
号就会莫名其妙地变成空格。比如,
前端: $.get('/test?' + 'key=' + 'i am a + char');
后端: req.query.key === 'i am a char'
.
然后我就想到,可能是编码问题。果断将前端的key参数进行编码encodeURIComponent(key)
,然后发现一切都正常了。
故事进展
但是我还是蛮困惑的。前端在不编码的情况下,为什么空格能正常传值,而加号就不行?我在网上搜了好久,依然没有一个让我感到满意的答案。很多人说直接全局替换加号为%2B
就好啦(加号的编码)。其实不用替换这么麻烦,直接对整个字符串进行一次编码(encodeURIComponent(key)
)就可以啦,自然而然就会替换成%2B
了。
继续深入
然后,我断点调试了一下express
,惊奇地发现req.url
里面的值居然显示有加号:req.url === xxx?key=i%20am%20a%20+%20char
。也就是说,其实,加号已经传过来了!!!只是express把它转化成空格放在req.query
而已!!!为什么要这么做呢!!!
跟踪代码
为了进一步地了解发生了什么事,于是我开启debug模式。惊奇地发现代码如下
exports.decode = function (str) {
try {
return decodeURIComponent(str.replace(/\+/g, ' '));
} catch (e) {
return str;
}
};
还得多一句:为啥?为啥express要这么做?初初我以为这可能是express的bug,毕竟加号已经传过来了。但是现在我已经抛开这个想法了,人家是有意这么搞的。那也就是说,只要我修改这些代码,express是可以正常接收前端未经编码的参数值。
思考
- 我比较好奇这是一种怎样的机制。在不编码的情况下,为什么后端接收的空格变成编码后的
%20
,而加号会直接传过来了? - express团队为什么会将加号全局替换掉?为了安全着想?还是说,这是一种规范,大家得遵守?
最后的最后
当然是加号变成空格的解决方法啦
- 每个参数进行编码
- 貌似只有上面这种方案比较好(直接改express源码不太好吧)