Отключить все HTTP-сообщения об ошибках HTTP по умолчанию в Tomcat
По умолчанию Tomcat отправляет некоторый HTML-контент обратно клиенту, если он встречает что-то вроде HTTP 404. Я знаю, что через web.xml
a <error-page>
можно настроить для настройки этого содержимого.
Однако мне бы хотелось, чтобы Tomcat не отправлял ничего с точки зрения содержимого ответа (конечно, мне все равно нужен код состояния). Есть ли способ легко настроить это?
Я пытаюсь избежать A), явно отправляющего пустой контент в потоке ответов из моего Сервлета, и B) настройка пользовательских страниц ошибок для целой группы статусов ошибок HTTP в моем web.xml
.
Для некоторого фона я разрабатываю API HTTP и контролирую свой собственный контент ответа. Например, для HTTP 500 я заполняю некоторый XML-контент в ответ, содержащий информацию об ошибке. Для ситуаций, таких как HTTP 404, для HTTP-ответа достаточно HTTP-ответа, а отправление содержимого tomcat не требуется. Если есть другой подход, я открыт для его слушания.
Edit:
После продолжения расследования я все еще не могу найти пути решения. Если кто-то может окончательно сказать, что это невозможно, или предоставить ресурс доказательствам того, что он не сработает, я буду принимать это как ответ и попытаться его обойти.
Ответы
Ответ 1
Если вы не хотите, чтобы tomcat отображал страницу с ошибкой, не используйте sendError (...). Вместо этого используйте setStatus (...).
например. если вы хотите дать ответ 405, то вы делаете
response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
response.getWriter().println("The method " + request.getMethod() +
" is not supported by this service.");
Также не забудьте выбросить какие-либо Исключения из вашего сервлета. Вместо этого поймайте Исключение и, опять же, установите statusCode самостоятельно.
то есть.
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);
}
}
конечно, если вам не нужен какой-либо контент, тогда просто ничего не пишите писателю, просто установите статус.
Ответ 2
Несмотря на то, что это не отвечает именно на инструкцию "не отправлять ничего" по этому вопросу и на волне ответа Клайва Эванса, я узнал, что в 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 (я думаю, из-за чего-то, сообщенного по следующей ссылке <а2 > )
Ответ 3
Как сказал Хейкки, установка статуса вместо 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()
с длиной сообщения (кроме нуля) или вы можете оставить его на сервере
Ответ 4
Быстрый, слегка грязный, но простой способ остановить 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) {
}
}
}
Ответ 5
Несмотря на то, что он совместим с сервлетами, по соображениям безопасности я не хочу, чтобы tomcat или какой-либо другой контейнер Servlet отправляли данные об ошибках. Я тоже немного боролся с этим. После поиска и попытки решение можно суммировать как:
- как упоминалось выше, не используйте
sendError()
, используйте setStatus()
вместо
- например, например. Spring Использование безопасности
sendError()
хотя...
- напишите
Filter
, чтобы
а. перенаправляет вызовы на sendError()
до setStatus()
б. сбрасывает ответ в конце, чтобы предотвратить дальнейшее изменение контейнера ответа
Ниже показан небольшой пример фильтра сервлета.
Ответ 6
Почему бы просто не настроить элемент <error-page>
с пустой HTML-страницей?
Ответ 7
Хотя этот вопрос немного стар, я столкнулся с этой проблемой. Прежде всего, поведение Tomcat абсолютно корректно. Это для сервлета. Не следует изменять поведение Tomcat против спецификации. Как упоминалось в Heikki Vesalainen и mrCoder, используйте только setStatus
и setStatus
.
К кому это может относиться, я поднял билет с Tomcat, чтобы улучшить документы sendError
.