71

默认情况下,如果遇到 HTTP 404 之类的问题,Tomcat 会将一些 HTML 内容发送回客户端。我知道可以web.xml通过<error-page> 配置来自定义这些内容。

但是,我只是希望 Tomcat在响应内容方面不发送任何内容(当然,我仍然想要状态码)。有什么方法可以轻松配置吗?

我试图避免 A) 从我的 Servlet 的响应流上显式发送空内容,以及 B) 为我的web.xml.

对于某些背景,我正在开发一个 HTTP API 并控制我自己的响应内容。例如,对于 HTTP 500,我在包含错误信息的响应中填充了一些 XML 内容。对于像 HTTP 404 这样的情况,HTTP 响应状态对于客户端来说就足够了,而 Tomcat 正在发送的内容是不必要的。如果有不同的方法,我愿意听听。

编辑: 经过继续调查,我仍然找不到太多的解决方案。如果有人可以明确地说这是不可能的,或者提供有证据证明它不起作用的资源,我会接受它作为答案并尝试解决它。

4

8 回答 8

46

如果您不希望 tomcat 显示错误页面,请不要使用 sendError(...)。而是使用 setStatus(...)。

例如,如果您想给出 405 响应,那么您可以

response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);      
response.getWriter().println("The method " + request.getMethod() + 
   " is not supported by this service.");

还要记住不要从您的 servlet 中抛出任何异常。而是捕获异常,然后再次设置您自己的状态代码。

IE

protected void service(HttpServletRequest request,
      HttpServletResponse response) throws IOException {
  try {

    // servlet code here, e.g. super.service(request, response);

  } catch (Exception e) {
    // log the error with a timestamp, show the timestamp to the user
    long now = System.currentTimeMillis();
    log("Exception " + now, e);
    response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    response.getWriter().println("Guru meditation: " + now);
  }
}

当然,如果您不想要任何内容​​,那么就不要给作者写任何东西,只需设置状态即可。

于 2009-09-20T13:39:30.910 回答
45

虽然这并没有完全回应关于问题的“不发送任何东西”声明,并且在Clive Evans 的回答浪潮中,我发现在 tomcat 中你可以让那些太多冗长的文本从错误页面中消失而无需创建自定义 ErrorReportValve。

您可以通过“server.xml”上的 2 个参数“showReport”和“showServerInfo”来完成此自定义 ErrorReportValve:

<Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" />

链接到官方文档

在 tomcat 7.0.55 上为我工作,在 tomcat 7.0.47 上对我不起作用(我认为是因为以下链接http://www.mail-archive.com/users@tomcat.apache.org /msg113856.html )

于 2014-08-11T07:14:53.193 回答
13

阻止 Tomcat 发送任何错误主体的快速、略微肮脏但简单的方法是针对 tomcat 主机调用 setErrorReportValveClass,并使用自定义错误报告阀覆盖报告以不执行任何操作。IE:

public class SecureErrorReportValve extends ErrorReportValve {

@Override
protected void report(Request request,Response response,Throwable throwable) {
}

}

并将其设置为:

  ((StandardHost) tomcat.getHost()).setErrorReportValveClass(yourErrorValveClassName);

如果你想发送你的消息,并且只是认为 Tomcat 不应该搞砸它,你想要一些类似的东西:

@Override
protected void report(final Request request, final Response response, final Throwable throwable) {
    String message = response.getMessage();
    if (message != null) {
        try {
            response.getWriter().print(message);
            response.finishResponse();
        } catch (IOException e) {
        }
    }
}
于 2011-11-17T11:12:20.920 回答
10

虽然它符合 Servlet 规范,但出于安全原因,我不希望 tomcat 或任何其他 Servlet 容器发送错误详细信息。我也为此苦苦挣扎。经过搜索和尝试,解决方法可以总结为:

  1. 正如其他人提到的,不要使用sendError()setStatus()而是使用(在 Jersey 框架中你可以选择
  2. 像 Spring Security 这样的框架sendError()虽然使用...
  3. 写一个Filter那个
    。将呼叫重定向sendError()setStatus()
    b。最后刷新响应以防止容器进一步修改响应

可以在此处找到执行此操作的一个小示例 servlet 过滤器

于 2013-01-16T09:47:18.837 回答
9

正如Heikki所说,设置状态而不是sendError()导致Tomcat不接触响应实体/正文/有效负载。

如果您只想发送没有任何实体的响应标头,例如在我的情况下,

response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);

成功了。使用Content-Length: 0print()即使使用也不会产生任何影响,例如:

response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.getWriter().print("this string will be ignored due to the above line");

客户收到类似的东西:

HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 0
Date: Wed, 28 Sep 2011 08:59:49 GMT

如果您想发送一些错误消息,请使用setContentLength()带有消息长度(不为零)或者您可以将其留给服务器

于 2011-09-28T09:04:55.307 回答
2

虽然这个问题有点老了,但我也遇到了这个问题。首先,Tomcat的行为是绝对正确的。这是每个 Servlet 规范。不应该根据规范改变 Tomcat 的行为。正如 Heikki Vesalainen 和 mrCoder 所提到的,使用setStatusand setStatusonly。

对于它可能关心的人,我已经向 Tomcat 提出了一张票,以改进sendError.

于 2012-11-23T21:16:34.473 回答
2

配置<error-page>元素web.xml

编辑$CATALINA_HOME/conf/web.xml,在最后添加以下内容<error-page>,保存并重启tomcat

<web-app>

...
...
...

    <error-page>
        <error-code>404</error-code>
        <location>/404.html</location>
    </error-page>

    <error-page>
        <error-code>500</error-code>
        <location>/500.html</location>
    </error-page>

    <error-page>
        <error-code>400</error-code>
        <location>/400.html</location>
    </error-page>

</web-app>
  • 即使我实际上没有为那些指定的location值创建有效的路由(例如/400.html) ,它也能像我预期的那样工作得很好

在此处输入图像描述

在此处输入图像描述

于 2018-11-28T08:15:57.007 回答
1

为什么不用<error-page>空的 HTML 页面来配置元素呢?

于 2009-04-27T17:51:03.550 回答