問(wèn)題來(lái)源
最近碰到一個(gè)很奇怪的問(wèn)題,js進(jìn)行網(wǎng)絡(luò)請(qǐng)求的時(shí)候,只要帶上+符號(hào),nodejs(express框架)中的req.query.key的值里面的+號(hào)就會(huì)莫名其妙地變成空格。比如,
前端: $.get('/test?' + 'key=' + 'i am a + char');
后端: req.query.key === 'i am a char'.
然后我就想到,可能是編碼問(wèn)題。果斷將前端的key參數(shù)進(jìn)行編碼encodeURIComponent(key),然后發(fā)現(xiàn)一切都正常了。
故事進(jìn)展
但是我還是蠻困惑的。前端在不編碼的情況下,為什么空格能正常傳值,而加號(hào)就不行?我在網(wǎng)上搜了好久,依然沒(méi)有一個(gè)讓我感到滿意的答案。很多人說(shuō)直接全局替換加號(hào)為%2B就好啦(加號(hào)的編碼)。其實(shí)不用替換這么麻煩,直接對(duì)整個(gè)字符串進(jìn)行一次編碼(encodeURIComponent(key))就可以啦,自然而然就會(huì)替換成%2B了。
繼續(xù)深入
然后,我斷點(diǎn)調(diào)試了一下express,驚奇地發(fā)現(xiàn)req.url里面的值居然顯示有加號(hào):req.url === xxx?key=i%20am%20a%20+%20char。也就是說(shuō),其實(shí),加號(hào)已經(jīng)傳過(guò)來(lái)了?。?!只是express把它轉(zhuǎn)化成空格放在req.query而已?。?!為什么要這么做呢!??!
跟蹤代碼
為了進(jìn)一步地了解發(fā)生了什么事,于是我開(kāi)啟debug模式。驚奇地發(fā)現(xiàn)代碼如下
exports.decode = function (str) {
try {
return decodeURIComponent(str.replace(/\+/g, ' '));
} catch (e) {
return str;
}
};
還得多一句:為啥?為啥express要這么做?初初我以為這可能是express的bug,畢竟加號(hào)已經(jīng)傳過(guò)來(lái)了。但是現(xiàn)在我已經(jīng)拋開(kāi)這個(gè)想法了,人家是有意這么搞的。那也就是說(shuō),只要我修改這些代碼,express是可以正常接收前端未經(jīng)編碼的參數(shù)值。
思考
- 我比較好奇這是一種怎樣的機(jī)制。在不編碼的情況下,為什么后端接收的空格變成編碼后的
%20,而加號(hào)會(huì)直接傳過(guò)來(lái)了? - express團(tuán)隊(duì)為什么會(huì)將加號(hào)全局替換掉?為了安全著想?還是說(shuō),這是一種規(guī)范,大家得遵守?
最后的最后
當(dāng)然是加號(hào)變成空格的解決方法啦
- 每個(gè)參數(shù)進(jìn)行編碼
- 貌似只有上面這種方案比較好(直接改express源碼不太好吧)