问题起因: 
   
客户订购了一关键字为"e+h
变送器"
, 在首页推荐广告中,会根据用户在search
搜索过的关键字进行一个匹配投放。技术实现是UED
通过JS
获取cookie
中的h_keys
内容,拼装到 http://xxxxx/advert/ctp_advert.htm?num=4&keyword=
{keyword}

这里取出来对应的cookie
信息为中文,最后通过一个ajax
发起一个GET请求。

所以针对最后的请求是:http://xxxxxx/advert/ctp_advert.htm?num=
4&keyword=e+h
变送器。 而在服务端接受到对应的请求参数时,发现参数为:e h
变送器, +
号没了。 初步怀疑跟URL规范相关,需要进行url encode


问题分析:

查了下JS encode
的相关内容, 总于发现+
号的秘密。
   html
中因为一些非标准的做法,将+
等同于空格进行处理
(当Html
的表单被提交时, 每个表单域都会被Url
编码之后才在被发送。由于历史的原因,表单使用的Url
编码实现并不符合最新的标准。例如对于空格使用
的编码并不是%20
,而是+
号,如果表单使用的是Post
方法提交的,我们可以在HTTP
头中看到有一个Content-Type
的header
,值为 application/x-www-form-urlencoded
,大部分应用程序均能处理这种非标准实现的Url
编码)。
   
在搜索引擎中做了下尝试: 
    keyword =  e h
变送器  , url =
http:
//www.google.cn/search?hl=zh-CN&newwindow=1&q=e+h变送器

   (
空格被转化为+
号)
    keyword = e+ h
变送器 , url = http:
//www.google.cn/search?hl=zh-CN&newwindow=1&q=e%2Bh变送器

  (+
号被进行了转义为%2B
,程序才能正常处理)


问题解决:

思路1:

1. 
要想正常传输+
号而不被转义为空格,需要进行进行编码为%2B
。查了下几个编码函数,发现只有encodeURIComponent
才会对+
号进行编码处理。
    2. encodeURIComponent
默认为采用UTF-8
字符集,理论上只需要在原先的请求中添加_input_charset=utf-8(
由 pipeline
中的SetLocaleValve
进行解析)
,就可以得到正确的 e+h
变送器。
   
   
在实施过程中,发现结果并不是预期的那样。 客户端通过js encode
后,在服务端解析后一直是乱码。
查了下byte
,发现服务端一直是用GBK
在进行解析, 针对变送器的UTF-8
编码的byte
为{-27,-113,-104,-23,-128,-127}
,客户端用GBK
解析后变为{-27.-113.- 104.-23,-63,-63}
,针对最后两byte
因为字符不可见,导致全部被替换为-63
。网上查了下,针对 utf-8 -> gbk -> utf-8
在一定情况下就会出现该问题(http://lingqi1818.iteye.com/blog/348953
)


思路2


   
继续追查对应的_input_charset=utf-8
未生效的原因,DEBUG
看到在SetLocaleValve
中的确设置了 request.setCharsetEncoding
为utf-8
。初步怀疑是否跟jboss server
的配置有关,查了下跟URIEncoding
和useBodyEncodingForURI
设置有关。 目前公司所使用的jboss
为4.05
,对应俄tomact
配置中只指定了对应的URIEncoding=GBK
。正因为这样,导致设置的_input_charset
针对GBK
的提交没有效果
,还是按照GBK
进行解析。

1. 
考虑将请求由GET
换成POST
, 这样就可以使用_input_charset

但在实施过程中,和UED
沟通过程,针对POST
的会引起一个跨域请求的问题。此方案又只能做罢


思路3

(
实践成功)



   
    1.  UED
进行伪url encode
的实现 ,
将+
号进行%2B
的编码。
因为目前JS
中没有现成的函数,这里只是通过replace(/\+/g,
'%2B')
进行了转化。



针对+
号的处理,针对不同的业务场景需要不同的处理方案,描述下几种场景:
1.
非Ajax
请求
   
可以直接使用Form
表单的 GET ,POST
的urlencode
协议,自动实现+ => %2B
的转化
2.  Ajax
请求
    * GET
请求 :
很无奈,只能使用方案3
,人为进行+
号转化。
    * POST
请求(
同一应用,非跨域请 求) : 
使用encodeURIComponent + 
_input_charset=utf-8
指定编码进行处理。

ps:
前面提的这几种方案,都是基于+
号是正常的业务场景进行考虑。同时我们也可以从业务层面进行一个梳理,+
号处理是否有其必要性,能从业务数据入口直接规避 那就最好了。

背景知识:


URIEncoding
和useBodyEncodingForURI

对于URL
提交的数据和表单中GET
方式提交的数据,在接收数据的JSP
中设置request.setCharacterEncoding
参数是不行的, 因为在Tomcat5.0
中,默认情况下使用ISO- 8859-1
对URL
提交的数据和表单中GET
方式提交的数据进行重新编码(解码),而不使用该参数对URL
提交的数据和表单中GET
方式提交的数据进行 重新编码(解码)。要解决该问题,应该在Tomcat
的配置文件的Connector
标签中设置useBodyEncodingForURI
或者 URIEncoding
属性,其中useBodyEncodingForURI
参数表示是否用
request.setCharacterEncoding
参数对URL
提交的数据和表单中GET
方式提交的数据进行重新编码
,在默认情 况下,该参数为false
(Tomcat4.0
中该参数默认为true
); URIEncoding
参数
指定对所有GET
方式请求(包括URL
提交的数据和表单中GET
方式提交的数据)进行统一的重新编码(解码)的编码

URIEncoding
和useBodyEncodingForURI
区别是,URIEncoding
是对所有GET
方式的请求的数据进行统一的重新编码 (解码),而useBodyEncodingForURI
则是根据响应该请求的页面的request.setCharacterEncoding
参数对数
据进行的重新编码(解码),不同的页面可以有不同的重新编码(解码)的编码。所以对于URL
提交的数据和表单中GET
方式提交的数据,可以修改 URIEncoding
参数为浏览器编码或者修改useBodyEncodingForURI
为true
,并且在获得数据的JSP
页面中 request.setCharacterEncoding
参数设置成浏览器编码。


为什么需要Url
编码
1.  Url
中有些字符会引起歧义 , =,&
号等
2.  Url
的编码格式采用的是ASCII
码,而不是Unicode
,这也就是说你不能在Url
中包含任何非ASCII
字符,例如中文

哪些字符需要编码
RFC3986
文档规定,Url
中只允许包含英文字母(a-zA-Z
)、数字(0-9
)、-_.~4
个特殊字符以及所有保留字符。
Url
可以划分成若干个组件,协议、主机、路径等。RFC3986
中指定了以下字符为保留字符: ! * ' ( ) ; : @ & =
+
$ , / ? # [ ]

如何对Url
中的非法字符进行编码
Url
编码通常也被称为百分号编码(Url Encoding
,also
known as percent-encoding
),是因为它的编码方式非常简单,使用%
百分号加上两位的字符——0123456789ABCDEF——
代表一个字节的 十六进制形式。Url
编码默认使用的字符集是US-ASCII
。例如a
在US-ASCII
码中对应的字节是0x61
,那么Url
编码之后得到的就是%
61
,我们在地址栏上输入http:
//g.cn/search?q=%61%62%63,实际上就等同于在google

上搜索abc

了。又如@

符号在
ASCII
字符集中对应的字节为0x40
,经过Url
编码之后得到的是%40

[故障引起的故事]URL中带加号的处理的更多相关文章

  1. URL中带加号的处理

    问题起因:      客户订购了一关键字为"e+h 变送器" , 在首页推荐广告中,会根据用户在search 搜索过的关键字进行一个匹配投放.技术实现是UED 通过JS 获取coo ...

  2. IE浏览器url中带中文报错的问题;以及各种兼容以及浏览器问题总结

    1.解决IE浏览器url带中文报错 /* encodeURI()解决IE浏览器请求url中带中文报错的问题 */ URL = encodeURI("<%=basePath%>ve ...

  3. URL参数带加号“+”AJAX传值失败的解决方法

    URL中参数的值有加号,虽然请求的URL中含有加号,但是GET的时候却得不到加号! 解决办法,用JavaScript的encodeURIComponent函数对加号进行编码. 如str="a ...

  4. url中带有加号的处理方法

    最近项目中出现了一个问题,图片的路径正确,但是转成URL之后无法找到... 找了各种原因之后,最后注意到URL中的图片名称和本地路径名称有点不一样,如下图 1.URL图片 2.本地路径 上网查了一下发 ...

  5. apache使用.htaccess文件中RewriteRule重定向后,URL中的加号无法解析

    今天在使用.htaccess做伪静态的时候,发生一件怪事,URL里存在C++时会有问题,在处理C++这个词的时候,无论如何,$_GET都得不到++,只能得到C空格. 一开始我以为是没用urlencod ...

  6. GBK 编码时 url 中带中文参数的问题

    项目中遇到的 GBK 编码问题,记录如下. 将代码精简为: <!DOCTYPE HTML> <html> <meta charset="gb2312" ...

  7. ASP.NET MVC Url中带点号出现404错误的解决方案

    由于项目需求,项目的路由设计如下 config.Routes.MapHttpRoute( name: "Get/Put Sku", routeTemplate: "api ...

  8. 获取url中带的参数

    本文目前只针对url中一个参数的 function getQueryString(name) { var reg = new RegExp("(^|&)" + name + ...

  9. nginx配置url中带问号的rewrite跳转

    今天收到一个需求,要将一个带查询参数的url跳转到另外一个静态url,安装常规的rewrite规则,如: rewrite ^/a.html?id=67$ http://zt.epython.cn/20 ...

随机推荐

  1. 阿里巴巴Java开发手册-集合处理

    1. [强制]关于 hashCode 和 equals 的处理,遵循如下规则:      1) 只要重写 equals ,就必须重写 hashCode .      2) 因为 Set 存储的是不重复 ...

  2. sql server 2008数据库 降为 sql server 2005数据库 最终方案总结

    由于xx原因,sql server 要降级,所以有了下文.... 一 直接 通过sql server 自带工具 生成脚本即可,具体操作方法如下: 1.打开 Microsoft Sql Server M ...

  3. wxWidgets:wxApp概述

    在我们编写wxWidgets应用程序的时候,我们不需要为之定义一个main函数:不过我们需要实现wxApp派生类的一个成员函数OnInit,它的地位大致等价于一般C++程序中的main. 一般来说On ...

  4. 垃圾收集器之:CMS收集器

    HotSpot JVM的并发标记清理收集器(CMS收集器)的主要目标就是:低应用停顿时间.该目标对于大多数交互式应用很重要,比如web应用.在我们看一下有关JVM的参数之前,让我们简要回顾CMS收集器 ...

  5. autopy的使用探索

    autopy这个包可以直接操作电脑的一些行为,比如点击,移动鼠标啥的,但是可能只使用于windows,用处有限,不过做个简单的游戏辅助还是可以的. 网上资料贼少,很多不能用的,现总结一些可以用的放在这 ...

  6. [UE4]解析json数据

    正常的json对象是可以使用单引号的,但是在UE4中的json解析,不能如下使用单引号: {‘name’:'张三'} 而是要使用双引号写成: {"name":"张三&qu ...

  7. uploadify是通过flash上传,服务器获取type为application/octet-stream

    uploadify是通过flash上传,服务器获取type为application/octet-stream,因此允许上传的类型要加上application/octet-stream

  8. Web Api in Orchard

    Web Api in Orchard Web Api is available in Orchard. You can implement a web api to fit your needs in ...

  9. 一点ExtJS开发的感悟

    虽然项目一直采用ExtJS作为前端开发,接触到了一些ExtJS 的一些场景界面,自己也尝试封装一些组件,对于开发70%基本可以满足需求.遇到最为麻烦的就是Ext的模版或者直接拼接字符串再进行eval转 ...

  10. JAVA中关于set()和get()方法的理解及使用

    对于JAVA初学者来说,set和get这两个方法似乎已经很熟悉了,这两个方法是JAVA变成中的基本用法,也是出现频率相当高的两个方法. 为了让JAVA初学者能更好的理解这两个方法的使用和意义,今天笔者 ...