java - Deshabilitar todo el contenido predeterminado de respuesta de error HTTP en Tomcat
servlets httpresponse (7)
¿Por qué no simplemente configurar el elemento <error-page>
con una página HTML vacía?
Por defecto, Tomcat envía algo de contenido HTML al cliente si encuentra algo así como un HTTP 404. Sé que a través de web.xml
se puede configurar una <error-page>
para personalizar este contenido.
Sin embargo, me gustaría que Tomcat no envíe nada en términos de contenido de respuesta (aún así me gustaría el código de estado, por supuesto). ¿Hay alguna forma de configurar esto fácilmente?
Estoy tratando de evitar A) enviar contenido explícitamente vacío en la secuencia de respuesta desde mi Servlet, y B) configurar páginas de error personalizadas para un montón de estados de error HTTP en mi web.xml
.
Para algunos antecedentes, estoy desarrollando una API HTTP y estoy controlando mi propio contenido de respuesta. Entonces, para un HTTP 500, por ejemplo, estoy poblando algún contenido XML en la respuesta que contiene información de error. Para situaciones como HTTP 404, el estado de respuesta HTTP es suficiente para los clientes, y el contenido que envía el gato es innecesario. Si hay un enfoque diferente, estoy abierto a escucharlo.
Editar: después de una investigación continua, todavía no puedo encontrar mucho en el camino de una solución. Si alguien puede decir definitivamente que esto no es posible, o proporciona un recurso con evidencia de que no funcionará, lo aceptaré como una respuesta y trataré de evitarlo.
Aunque es compatible con las especificaciones de Servlet, por razones de seguridad no quiero que ni Tomcat ni ningún otro contenedor Servlet envíe detalles de error. Luché con esto también un poco. Después de buscar e intentar, la solución se puede resumir como:
- como otros mencionaron, no use
sendError()
, usesetStatus()
lugar - marcos como por ejemplo Spring Security usan
sendError()
aunque ... - escribe un
Filter
que
a. redirige las llamadas asendError()
asetStatus()
segundo. vacía la respuesta al final para evitar que el contenedor modifique aún más la respuesta
Un pequeño ejemplo de filtro de servlet haciendo esto puede encontrarse aquí .
Aunque esta pregunta es un poco vieja, me encontré con este problema también. En primer lugar, el comportamiento de Tomcat es absolutamente correcto. Esto es por especificación de servlet. Uno no debe alterar el comportamiento de Tomcat contra la especificación. Como mencionan Heikki Vesalainen y mrCoder, use setStatus
y setStatus
solamente.
A quien corresponda, he elevado un ticket con Tomcat para mejorar los documentos de sendError
.
Aunque esto no responde exactamente a la afirmación "no enviar nada" sobre la pregunta, y en la ola de la respuesta de Clive Evans , descubrí que en Tomcat puedes hacer que esos textos demasiado prolijos se alejen de las páginas de error sin crear una ErrorReportValve personalizada.
Puede realizar esta personalización de ErrorReportValve a través de los 2 parámetros "showReport" y "showServerInfo" en su "servidor.xml":
<Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" />
Enlace a la documentación oficial .
Funcionó para mí en tomcat 7.0.55, no funcionó para mí en tomcat 7.0.47 (creo que debido a algo reportado en el siguiente enlace http://www.mail-archive.com/[email protected]/msg113856.html )
Como dijo Heikki, establecer el estado en lugar de sendError()
hace que el Tomcat no toque la entidad de respuesta / cuerpo / carga útil.
Si solo quieres enviar los encabezados de respuesta sin ninguna entidad, como en mi caso,
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
Hace el truco. Con Content-Length: 0
, la print()
no tendrá efecto incluso si se usa, como:
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.getWriter().print("this string will be ignored due to the above line");
el cliente recibe algo como:
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
Si desea enviar un mensaje de error, use setContentLength()
con la longitud del mensaje (distinto de cero) o puede dejarlo en el servidor
La manera rápida, ligeramente sucia, pero fácil de evitar que Tomcat envíe cualquier cuerpo de error es llamar a setErrorReportValveClass contra el servidor tomcat, con una válvula personalizada de informe de errores que anula el informe para no hacer nada. es decir:
public class SecureErrorReportValve extends ErrorReportValve {
@Override
protected void report(Request request,Response response,Throwable throwable) {
}
}
y configurarlo con:
((StandardHost) tomcat.getHost()).setErrorReportValveClass(yourErrorValveClassName);
Si desea enviar su mensaje, y simplemente pensar que Tomcat no debería meterse con él, quiere algo como:
@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) {
}
}
}
Si no desea que tomcat muestre una página de error, entonces no use sendError (...). En su lugar, use setStatus (...).
por ejemplo, si desea dar una respuesta 405, entonces lo hace
response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
response.getWriter().println("The method " + request.getMethod() +
" is not supported by this service.");
Recuerde también no arrojar ninguna excepción de su servlet. En cambio, capture la Excepción y, de nuevo, establezca el código de estado usted mismo.
es decir
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);
}
}
por supuesto, si no quiere ningún contenido, simplemente no escriba nada al escritor, simplemente configure el estado.