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 ERROR 400 Bad Request

微博中出现http/1.1 400 Bad Request怎么解决。

HTTP 400 Bad request 原因

nginx:400 Bad RequestThe plain HTTP request

400 BAD request HTTP错误码是啥意思?

RPC 失败; HTTP 400 curl 22 The requested URL returned error: 400 Bad Request