url编码实践
此前碰到两个问题:
1. {}字符报错 rfc3986
2. 含有% & 号的参数传递到tomcat,参数接收为null
3.webview没取到中文参数
第一个问题:
http://blog.csdn.net/flyingnet/article/details/78143429
今天在Tomcat 7.0.81进行测试时,发现一个BUG,前台通过ajax访问后台controller时,无法进行页面跳转。Tomcat控制台报错,错误信息如下:
信息: Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
at org.apache.coyote.http11.InternalAprInputBuffer.parseRequestLine(InternalAprInputBuffer.java:235)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1028)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2549)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2538)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:662)
经过分析,发现问题是由URL中一个参数params引起的,
这个参数通过JSON2.stringify()转换为一个对象数组,所以包含了{},而恰恰就是这一步在Tomcat 7.0.81版本中出现 了问题,请求链接都是400的状态,就是请求参数有误。
这个问题是由于Tomcat的新版本中增加了一个新特性,就是严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])。(连带%,本身转义符,所以不属于保留字符,)
既然分析出了原因,那么就要找解决方案了,其实,解决办法很简单,就是使用encodeURIComponent或encodeURI对包含{}的URL进行编码,这样就可以解决该问题。当然,还有一种办法就是更换Tomcat为支持大括号{}的版本。
{}进去之后,tomcat不接收报错,解决方法,urlencode通过
注意urlencode 某些实现是不能对保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ] 进行编码的(废话,关键字被你编码了,服务器还怎么取参数),但可以对%进行编码,编码出%25
第二个问题:
http://lwjlaser.iteye.com/blog/1055359
测试最近的代码发现,有一个servlet处理通过post方式传递过来的参数的时候偶尔出现乱码,并提示错误“org.apache.tomcat.util.http.Parameters processParameters Parameters: Character decoding failed”,开始以为是编码问题,google了一大堆关于编码的问题,各种测试还是无法解决这个问题。于是把出错的参数调了出来用类似二分法的方式慢慢筛查参数,最后锁定在参数中的%上,因为要传递的参数不是经常出现%,所以就出现偶尔出错的现象。解决方法就是把参数中的“%”替换为“%25”,修改代码为
- parameter = parameter.replace("%","%25")
,问题解决。
下面附录是URL中的特殊字符:
- URL中一些字符的特殊含义,基本编码规则如下:
- 1、空格换成加号(+)
- 2、正斜杠(/)分隔目录和子目录
- 3、问号(?)分隔URL和查询
- 4、百分号(%)制定特殊字符
- 5、#号指定书签
- 6、&号分隔参数
- 如果需要在URL中用到,需要将这些特殊字符换成相应的十六进制的值
- + %20
- / %2F
- ? %3F
- % %25
- # %23
- & %26
1. 非Ajax 请求
可以直接使用Form 表单的 GET ,POST 的urlencode 协议,自动实现+ => %2B 的转化
2. Ajax 请求
* GET 请求 : 很无奈,只能使用方案3 ,人为进行+ 号转化。
* POST 请求( 同一应用,非跨域请 求) : 使用encodeURIComponent + _input_charset=utf-8 指定编码进行处理。