Отключить все содержимое ответа об ошибке HTTP по умолчанию в Tomcat - PullRequest
67 голосов
/ 27 апреля 2009

По умолчанию Tomcat отправляет некоторое содержимое HTML обратно клиенту, если он обнаруживает что-то вроде HTTP 404. Я знаю, что через web.xml можно настроить <error-page> для настройки этого содержимого.

Однако, я бы хотел, чтобы Tomcat ничего не отправлял с точки зрения содержания ответа (мне, конечно, все еще нужен код состояния). Есть ли способ легко настроить это?

Я пытаюсь избежать A) явной отправки пустого содержимого в потоке ответов из моего сервлета и B) настройки пользовательских страниц ошибок для целой пачки состояний ошибок HTTP в моем web.xml.

Для некоторого фона я разрабатываю HTTP API и контролирую свой собственный контент ответов. Так, для HTTP 500, например, я заполняю некоторый контент XML в ответе, содержащем информацию об ошибке. Для ситуаций, подобных HTTP 404, статус ответа HTTP является достаточным для клиентов, и контент, который отправляет кот, не нужен. Если есть другой подход, я готов его услышать.

Edit: После продолженного расследования я все еще не могу найти много решений. Если кто-то может однозначно сказать, что это невозможно, или предоставить ресурсу доказательства того, что это не сработает, я приму это в качестве ответа и постараюсь обойти это.

Ответы [ 8 ]

44 голосов
/ 20 сентября 2009

Если вы не хотите, чтобы tomcat показывал страницу с ошибкой, не используйте sendError (...). Вместо этого используйте setStatus (...).

например. если вы хотите дать ответ 405, тогда вы делаете

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

Также помните, что вы не должны выбрасывать исключения из вашего сервлета. Вместо этого перехватите исключение и снова установите свой код состояния.

т.е.

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);
  }
}

Конечно, если вы не хотите никакого контента, просто ничего не пишите автору, просто установите статус.

36 голосов
/ 11 августа 2014

Хотя это не совсем точно отвечает на вопрос «не отправлять ничего» и на волне ответа Клайва Эванса , я обнаружил, что в tomcat вы можете сделать это слишком много подробные тексты удаляются со страниц ошибок без создания пользовательского ErrorReportValve.

Вы можете выполнить эту настройку ErrorReportValve с помощью 2-х параметров «showReport» и «showServerInfo» на вашем «server.xml»:

<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 )

10 голосов
/ 17 ноября 2011

Быстрый, немного грязный, но простой способ помешать Tomcat отправлять любое тело ошибки - вызвать setErrorReportValveClass для хоста tomcat с настраиваемым клапаном отчетов об ошибках, который переопределяет отчет, чтобы ничего не делать. то есть:

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) {
        }
    }
}
9 голосов
/ 28 сентября 2011

Как сказал Хейкки, установка статуса вместо sendError() заставляет Tomcat не касаться объекта ответа / тела / полезной нагрузки.

Если вы хотите только отправить заголовки ответа без какой-либо сущности, как в моем случае,

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

делает свое дело. С Content-Length: 0, print() не будет иметь эффекта, даже если используется, например:

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() с длиной сообщения (отличной от нуля) или вы можете оставить его на сервере

8 голосов
/ 16 января 2013

Хотя это и соответствует спецификации Servlet, по соображениям безопасности я не хочу, чтобы tomcat или какой-либо другой контейнер Servlet отправлял подробности об ошибках. Я тоже немного боролся с этим. После поиска и попытки решение можно суммировать как:

  1. как уже упоминалось, не используйте sendError(), используйте setStatus() вместо
  2. фреймворки, такие как, например, Spring Security использует sendError() хотя ...
  3. написать Filter, что
    а. перенаправляет звонки на sendError() на setStatus()
    б. очищает ответ в конце, чтобы предотвратить дальнейшее изменение контейнера контейнером

Небольшой пример фильтра сервлетов, который делает это, можно найти здесь .

2 голосов
/ 27 апреля 2009

Почему бы просто не настроить элемент <error-page> с пустой HTML-страницей?

1 голос
/ 28 ноября 2018

Настроить <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)

до

enter image description here

после

enter image description here

1 голос
/ 24 ноября 2012

Хотя этот вопрос немного устарел, я тоже столкнулся с этой проблемой. Во-первых, поведение Tomcat абсолютно правильно. Это в соответствии с Servlet Spec. Не следует изменять поведение Tomcat против спецификации. Как упоминали Хейкки Весалайнен и mrCoder, используйте только setStatus и setStatus.

Для кого это может касаться, я поднял билет с Tomcat, чтобы улучшить документы sendError.

...