java Tomcat 9:标题行不符合RFC 7230
我有一个在Tomcat 8.5.38上运行的应用程序。 现在我决定升级到Tomcat 9.0.27,GET请求和RFC 7230, Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing出现了问题
请求:
/api/vehicle/power_off?vehicleId=1428714&dtStart=2019-10-21 08:00:00&dtEnd=2019-10-21 08:30:00
它在浏览器(任何浏览器——IE、Opera、Chrome、FF)和另一个客户端(1C ERP系统)上都能完美运行
从浏览器升级版本后,它仍能正常工作,但从1C升级版本后,它不能正常工作。Tomcat显示错误:
28-Oct-2019 17:29:26.201 INFO [http-nio-8080-exec-3] org.apache.coyote.http11.Http11Processor.service Error parsing HTTP request header
Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: The HTTP header line [get /api/vehicle/power_off?deviceId=1428714&dtStart=2019-10-21%2008:00:00&dtEnd=2019-10-21%2008:30:00 HTTP/1.1: ] does not conform to RFC 7230 and has been ignored.
at org.apache.coyote.http11.Http11InputBuffer.skipLine(Http11InputBuffer.java:962)
at org.apache.coyote.http11.Http11InputBuffer.parseHeader(Http11InputBuffer.java:825)
at org.apache.coyote.http11.Http11InputBuffer.parseHeaders(Http11InputBuffer.java:564)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:309)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
在我的开发机器(MacOS+Tomcat 9.0.24)和生产服务器(Ubuntu 16.04+Tomcat 9.0.27)上也存在同样的错误
原因是datetime参数中的冒号。当我从查询字符串中删除冒号(只留下“2019-10-21 080000”)时,请求按预期工作(错误为“datetime无法解析…”)。此外,当我手动将冒号更改为“%3A”时,请求会工作并返回正常结果
然后我将relaxedQueryChars参数添加到带有冒号的Tomcat连接器中(尽管冒号是允许的):
relaxedQueryChars=':[]|{}^\`"<>'
但它仍然失败了
我的请求在8中有效,但在9中无效,8和9 Tomcat版本之间有什么区别? 我能在Tomcat中做些什么来让这个请求生效吗?在客户端更改请求是一项非常艰巨的任务
# 1 楼答案
我认为区别在于Tomcat 9。x收紧了URL中应该允许未编码的内容,因此从技术角度来看,Tomcat 9没有问题。十、问题在于早期的Tomcat版本,以及浏览器没有严格遵循规范
这就是说,我无法确定任何特定的修复为您触发了这个问题,我也无法在the Release Notes中看到任何东西
从the Tomcat 9.0 documentation到
relaxedQueryChars
:HTTP/1.1规范要求在URI查询字符串中使用某些字符时进行%nn编码。不幸的是,包括所有主要浏览器在内的许多用户代理都不符合该规范,并且以未编码的形式使用这些字符。为了防止Tomcat拒绝此类请求,可以使用此属性指定允许的其他字符。如果未指定,则不允许使用其他字符该值可以是以下字符的任意组合:“<;>;[\]^`{124;}。该值中的任何其他字符都将被忽略。
注意最后两句话。没有提到冒号字符,因此它“将被忽略”
我不这么认为,但真正的问题是,您没有在参数中编码冒号,而且您已经提到,这解决了这个问题See this SO answer,尤其是最后一句:
冒号是具有特殊含义的保留字符,因此必须在参数中对其进行编码
注:
另见Bug 62273 - Add support for alternate URL specification。虽然它并没有具体解决冒号字符的问题,但有一个有趣的讨论是关于浏览器如何没有遵守RFC 3986 (Uniform Resource Identifier (URI): Generic Syntax)
您从Tomcat收到的错误消息很模糊,可能需要改进。也许会向他们提出错误报告