IE浏览器连接WebSocket报错:java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986

  在项目开发中整合了 WebSocket,本来没什么问题了,但是偶尔发现用 IE 浏览器打开 web 端不能推送消息,因为 PC 端与服务器建立连接失败了。网上查了很多资料,

又看了看源码,都不对症;又怀疑是 SpringBoot 版本的问题,但是换了版本还是不行。楼主用 demo 跑了一遍发现没有问题,但就是在项目中不能建立连接,再认真调试发

现第一次建立连接的时候后台有一个报错,内容如下:

2020-03-25 09:12:37.348  INFO 5580 --- [0.0-8080-exec-3] o.apache.coyote.http11.Http11Processor   : Error parsing HTTP request header
 Note: further occurrences of HTTP request 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.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:
476) ~[tomcat-embed-core-9.0.31.jar:9.0.31]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:
260) ~[tomcat-embed-core-9.0.31.jar:9.0.31]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:
65) [tomcat-embed-core-9.0.31.jar:9.0.31]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:
868) [tomcat-embed-core-9.0.31.jar:9.0.31]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:
1639) [tomcat-embed-core-9.0.31.jar:9.0.31]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:
49) [tomcat-embed-core-9.0.31.jar:9.0.31]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:
1149) [na:1.8.0_202]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:
624) [na:1.8.0_202]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:
61) [tomcat-embed-core-9.0.31.jar:9.0.31]
at java.lang.Thread.run(Thread.java:
748) [na:1.8.0_202]

  报错:Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986 说的很明白,貌似是什么特殊字符引起的?真是奇了

怪了,楼主就是在建立 WebSocket 连接的时候传了一个 Json 字符串而已,没有什么奇怪的字符才对。用这个报错描述再查百度了一下,终于找到了想要的答案。

  这个问题跟 Tomcat 版本有关,Tomcat 高版本中的一个新特性:严格按照 RFC 3986 规范进行访问解析,而 RFC 3986 规范定义了 Url 中只允许包含英文字母(a-zA-Z)、

数字(0-9)、-_.~4 个特殊字符以及所有保留字符 (RFC3986 中指定了以下字符为保留字符:! * ’ () ; : @ & = + $ , / ? # [])。很明显,确实是字符引起的报错,楼主在 url 中传

了一段 json,传入的参数中有”{“和“"”,花括号和双引号不在 RFC3986 中的保留字段中,所以就报错了。

  楼主的解决办法是,建立连接的时候,在传的 json 字符串参数中把“{“和”}”这两个字符去掉,同时前端的 json 自己拼接,里面的字段名和字符串都用单引号,比如建立连接

正常的路径是 ws://127.0.0.1:8080/webSocket/{param},要接收一个参数作为鉴权和业务需要,为了避免参数中的字符问题,拼接一个这样的地址:

    ws://127.0.0.1:8080/webSocket/'userId':'3a05d7f26c8246bbbbec6b80da86c741','token':'090139d320b4257b43a4b3fb4faf9fda3527344e8145'

后台接收到参数以后,自己加上前后的花括号,这样就可以解析 json 了,简单粗暴,但是有效,哈哈哈。。。

  当然了,网上正规的解决方法:

  参考https://bz.apache.org/bugzilla/show_bug.cgi?id=60594,说从以下版本开始,有配置项能够关闭 / 配置这个行为:

    8.5.x 系列的:8.5.12 onwards
    8.0.x 系列的:8.0.42 onwards
    7.0.x 系列的:7.0.76 onwards

  解决办法就是:…/conf/catalina.properties 中,找到最后注释掉的一行

    #tomcat.util.http.parser.HttpParser.requestTargetAllow=|  ,

  改成

    tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}

  然后去掉这句话的注释。

  这种方法楼主没有试过,有兴趣的同学可以自己尝试一下。