Tomcat 9:标头行不符合RFC 7230

时间:2019-10-28 15:20:24

标签: java http tomcat url

我有一个正在使用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)上,存在相同的错误。

原因是日期时间参数中的冒号。当我从查询字符串中删除冒号(仅保留“ 2019-10-21 080000”)时,请求将按预期工作(错误“无法解析datetime ...”)。同样,当我手动将冒号更改为“%3A”时,请求有效并返回正常结果。

然后我用冒号(尽管允许使用冒号)将relaxedQueryChars参数添加到Tomcat连接器:

relaxedQueryChars=':[]|{}^\`"<>'

它仍然失败。

我的请求可以在8中使用,而在9中则不能,在8和9 Tomcat版本之间有什么区别? 我可以在Tomcat中做些什么使此请求生效?在客户端更改请求是一项艰巨的任务...

1 个答案:

答案 0 :(得分:1)

  

我要求的8和9个Tomcat版本之间有什么区别   在8中有效,但在9中无效?

我认为不同之处在于Tomcat 9.x加强了在URL中应允许对其进行未编码的内容,因此从技术角度来看,Tomcat 9.x没问题。问题出在早期的Tomcat版本中,浏览器未严格遵循规范。

也就是说,我无法识别出任何引发您此问题的特定修复程序,也无法在the Release Notes中看到任何内容。

  

我将冒号添加为带有冒号的Tomcat连接器   (尽管冒号是允许的符号)...但仍然失败。

the Tomcat 9.0 documentationrelaxedQueryChars

HTTP / 1.1规范要求在URI查询字符串中使用某些字符时必须进行%nn编码。不幸的是,包括所有主要浏览器在内的许多用户代理都不符合该规范,并且以未编码形式使用这些字符。为了防止Tomcat拒绝此类请求,可以使用此属性指定允许的其他字符。如果未指定,则不允许其他字符。 值可以是以下字符的任意组合:“ <> [\] ^`{|}。值中存在的任何其他字符将被忽略。

注意最后两个句子。没有提到冒号,因此它是“ 将被忽略”。

  

在Tomcat中我可以做些什么来使此请求正常工作?

我不这么认为,但是真正的问题是您没有在参数中编码冒号,并且您已经提到这可以解决问题。 See this SO answer,尤其是最后一句话:

There are reserved characters, that have a reserved meanings, those are delimiters — :/?#[]@ — and subdelimiters — !$&'()*+,;=

There is also a set of characters called unreserved characters — alphanumerics and -._~ — which are not to be encoded.

That means, that anything that doesn't belong to unreserved characters set is supposed to be %-encoded, when they do not have special meaning (e.g. when passed as a part of GET parameter).

冒号是具有特殊含义的保留字符,因此必须在参数中进行编码。

注意: