Tomcat 中 HTTP 400 Bad Request 的常见原因以及示例
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tomcat 中 HTTP 400 Bad Request 的常见原因以及示例相关的知识,希望对你有一定的参考价值。
参考技术A在web开发中, HTTP 400 Bad Request 是一种常见但却难以定位的问题, 通常是因为请求没有遵循 HTTP 标准. 原因看起来很直观, 但是在定位此类问题时, 往往需要花费极大的精力. 有以下几个难点:
在本片文章中, 会分享实际生产环境下的真实事例. 并且对Tomcat中所有400的情况给出了实际例子, 方便以后更直观的判断请求是否有问题.
本文基于 tomcat-embed-core-9.0.29
详见下一篇博文
由于对LB进行升级, 将流量从旧的LB切换到新的LB之后, 某些客户端的所有响应都变成了 400 BAD REQUEST.
客户端发送的请求头示例 "APPLICATION-VERSION : 519", 冒号前的空格即为非法字符.
Tomcat调用逻辑如下. 在parseHeader()方法中, 会使用isToken()方法检查请求头中是否有非法字符.
org.apache.coyote.http11.Http11Processor#service: parseHeaders and catch IllegalArgumentException
org.apache.coyote.http11.Http11InputBuffer#parseHeader: 检验请求头并在skipLine()中抛出llegalArgumentException. IS_TOKEN 是一个用来存储非法字符的位图, 非法字符包含 \' \' \',\' \'(\' \')\' \'\' 等.
org.apache.coyote.http11.Http11InputBuffer#skipLine: 抛出异常
这里总结了所有tomcat-embed-core-9.0.29中会返回HTTP 400 Bad Request的情况, 并给出了样例.
以下例子均为HTTP报文格式, case 0 是一个可以正确返回200的请求, 后续的例子是在case 0 的基础上进行改变, 改变的部分会以橙色标出, 导致400的关键字会以红色标出, 便于直观的发现问题.
200 Sample
200 Sample
org.apache.coyote.AbstractProcessor#line 302
400 Sample
org.apache.coyote.AbstractProcessor#line 337
Illegal characters logic: org.apache.tomcat.util.http.parser.HttpParser.DomainParseState#next
400 Sample
org.apache.coyote.AbstractProcessor#line 982
No example
org.apache.coyote.http11.Http11Processor#line 311
Character set: org.apache.tomcat.util.http.parser.HttpParser#IS_TOKEN
400 Sample for illegal character
400 Sample for blank
org.apache.coyote.http11.Http11Processor#line 609
400 Sample
org.apache.coyote.http11.Http11Processor#line 612
400 Sample
org.apache.coyote.http11.Http11Processor#line 660
Character set: org.apache.tomcat.util.http.parser.HttpParser#IS_USERINFO
400 Sample
org.apache.coyote.http11.Http11Processor#line 686
400 Sample
9. Start line中协议名称非法
org.apache.coyote.http11.Http11Processor#line 705
400 Sample
org.apache.coyote.http11.Http11Processor#line 713
Character set: org.apache.tomcat.util.http.parser.HttpParser#IS_ABSOLUTEPATH_RELAXED
400 Sample
org.apache.coyote.http11.Http11Processor#line 739
400 Sample
12. 请求头中含有多个Content-Length
org.apache.coyote.http11.Http11Processor#line 741
400 Sample
Tomcat 未重定向到 400 bad request 自定义错误页面
【中文标题】Tomcat 未重定向到 400 bad request 自定义错误页面【英文标题】:Tomcat is not redirecting to 400 bad request custom error page 【发布时间】:2019-03-19 18:06:16 【问题描述】:我们有 tomcat 9 web 服务器在生产中。我们面临的问题是,如果 tomcat 收到任何格式错误的 URL,我们希望为我们的应用程序显示自定义错误页面,如下所示
http://URL/|
或
http://URL/[
我在tomcat应用服务器的web.xml中添加了错误页面标签如下
<error-page>
<error-code>400</error-code>
<location>/error.html</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error.html</location>
</error-page>
我们在tomcat的webapps目录下的应用ROOT文件夹中有error.html。
每当用户尝试请求任何不存在的网页时,他都会收到正确对应于上述 404 错误代码的错误页面。
真正的问题是当用户在浏览器中输入格式错误的 URL(如http://URL/|)时,tomcat 无法重定向到 error.html
Tomcat 显示的是默认的 400 bad request 错误页面,而不是自定义错误页面。
【问题讨论】:
我们遇到了同样的问题。你最终解决了这个问题吗?谢谢。 仍然无法解析@stepanian 看起来这是一个错误,而不是我们做错了什么。我们可能应该通知 Tomcat 开发团队。 此问题仅存在于 tomcat 9 中。它只适用于 tomcat7 和 tomcat8 @stepanian 是的。它也适用于我的 Tomcat 8。看起来这是 Tomcat 9 中引入的错误。 【参考方案1】:对于嵌入式 Tomcat:
var tomcat = new org.apache.catalina.startup.Tomcat();
var host = (StandardHost) tomcat.getHost();
var errorReportValve = new org.apache.catalina.valves.ErrorReportValve();
errorReportValve.setShowReport(false);
errorReportValve.setShowServerInfo(false);
errorReportValve.setProperty("errorCode.0", "empty.html");
host.addValve(errorReportValve);
http://tomcat.apache.org/tomcat-9.0-doc/config/valve.html#Error_Report_Valve
https://tomcat.apache.org/tomcat-9.0-doc/api/org/apache/catalina/valves/ErrorReportValve.html
【讨论】:
【参考方案2】:这不是错误,这是配置问题。
Tomcat 9 改进了错误处理,以便将更多错误(尤其是在请求处理开始之前发生的错误)传递给标准错误处理机制,而不仅仅是返回错误代码。
在 URI 格式错误的情况下,Tomcat 无法解析 URI,因此 URI 无法映射到 Web 应用程序。因此,Tomcat 无法触发应用程序级别的错误处理,因为它无法识别应用程序。在这种情况下,错误由可以在 server.xml 中配置的ErrorReportValve 处理。
ErrorReportValve 的最新(ish)新增功能是能够以与每个 Web 应用程序错误页面配置类似的方式定义每个状态代码和/或异常类型的静态网页(即没有 Servlet 或 JSP,只有 HTML) .
错误报告阀示例:
<Valve className="org.apache.catalina.valves.ErrorReportValve"
errorCode.400="webapps/ROOT/error400.html"
errorCode.0="webapps/ROOT/errorOthers.html"
showReport="false"
showServerInfo="false" />
【讨论】:
我似乎无法在 Tomcat 文档或其他任何地方找到任何关于如何配置 ErrorReportValve 以返回预定义的静态 HTML 页面的示例。你能给我举个例子吗? @CFL_Jeff。见tomcat.apache.org/tomcat-9.0-doc/config/… 是的,现在为 Tomcat 9.0.53 实现了它并且它可以工作。塔。我建议注意errorCode.0
的特殊值。这样,如果它有很多上下文,您就可以集中保护整个服务器。【参考方案3】:
下面是https://***.com/a/55702749/2532710 之后的示例配置,以节省其他人的时间。 在 Host 标签内的 server.xml 中:
<Valve className="org.apache.catalina.valves.ErrorReportValve"
errorCode.400="webapps/ROOT/error400.html"
errorCode.0="webapps/ROOT/errorOthers.html"
showReport="false"
showServerInfo="false" />
将静态html error400.html ... errorOthers.html 放在CATALINA_BASE的webapps/ROOT中。
【讨论】:
CATALINA_BASE 在哪里?【参考方案4】:您可以编写自己的错误页面 https://aspiresoftware.in/blog/catalinatomcat-custom-error-report-valve-to-handle-errors-exceptions/
你必须把你的 jar 放在 tomcat 库中。
【讨论】:
以上是关于Tomcat 中 HTTP 400 Bad Request 的常见原因以及示例的主要内容,如果未能解决你的问题,请参考以下文章
微博中出现http/1.1 400 Bad Request怎么解决。
nginx:400 Bad RequestThe plain HTTP request
RPC 失败; HTTP 400 curl 22 The requested URL returned error: 400 Bad Request