之前,在开发的过程中,发现了一个很奇怪的问题,那就是关于get请求带来的字符乱码的问题,困扰了我很久,那就是在使用Get请求的时候,请求中带了参数 +
,而后,后台无论如何都收不到这个+
,只会显示空格,奇怪的是,当我把请求过来的URL
完整打印出来时却又是正确的,基本情况可以用下面的例子展示:
完整的get请求
http://www.test.com/test?a=21398+kjad
按道理,我后台想收到的应该是:
21398+kjad
但实际上收到的却是:
21398 kjad
出现这个问题后,本以为是前端的请求出了问题,于是,在后台把请求打印出来发现,完整的URL并没有变,依然是上面的请求:
http://www.test.com/test?a=21398+kjad
那么,是什么原因导致的呢?
后来网上查找了一下,发现很多人都遇到了和我一样的问题,其实,这是一个历史性的遗留问题,这篇博客这么写道:
html
中因为一些非标准的做法,将+
等同于空格
进行处理 (当Html
的表单被提交时,每个表单域都会被Url
编码之后才在被发送。由于历史的原因,表单使用的Url
编码实现并不符合最新的标准。例如对于空格使用的编码并不是%20
,而是+
号,如果表单使用的是Post
方法提交的,我们可以在HTTP
头中看到有一个Content-Type
的header
,值为application/x-www-form-urlencoded
,大部分应用程序均能处理这种非标准实现的Url
编码)。
可以看到,其实,当后端收到+
后,会以为是空格的编码,从而将其转换成了空格。(一般来讲,服务器会默认帮你做了这些处理的)
** Angular2中的坑 **
眼看着问题似乎解决了,于是乎,在Angular2中,我在使用params设置键值的时候,将键值encodeUrlComponent
了一下,本来准备坐等胜利的果实,结果却又仿佛一场噩梦:
后台依然有空格!!!
徘徊了许久、尝试了多次,依然不行,百无聊赖,只能看源码了:
在使用URLSearchParams
对象设置键值的时候,Angular2中的源码对字符有如下处理:
function standardEncoding(v) {
return encodeURIComponent(v)
.replace(/%40/gi, '@')
.replace(/%3A/gi, ':')
.replace(/%24/gi, '$')
.replace(/%2C/gi, ',')
.replace(/%3B/gi, ';')
.replace(/%2B/gi, '+')
.replace(/%3D/gi, '=')
.replace(/%3F/gi, '?')
.replace(/%2F/gi, '/');
}
看到这儿,真的忍不住想吐血,心里暗骂了angular2
一百遍。
大家看出什么问题了吗?
是的,它把我辛辛苦苦转化的%2B
又给转换回去了!!!!
写到这里,我真的没有明白,Angular2
为什么要这么做,浪费了我好多时间。
最后的解决方法也很简单很暴力了,直接自己拼接encodeUrlComponent
后的字符,不使用URLSearchParams
对象。