在項目開發中整合了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=|{}
然后去掉這句話的注釋。
這種方法樓主沒有試過,有興趣的同學可以自己嘗試一下。