Tengo un servlet que maneja ciertas solicitudes y respuestas HTTP. Quiero registrar el cuerpo de la respuesta antes de enviar de vuelta al cliente. ¿Hay alguna manera de que pueda capturar el cuerpo de la respuesta antes de que se envíe como un objeto HttpServletResponse
del servlet?Capturar y registrar el cuerpo de la respuesta
Respuesta
Si lo entiendo correctamente, ¿desea registrar la respuesta cuerpo? Esa es una tarea bastante costosa, pero si ese es el requisito comercial ...
Como @duffymo apuntado, un Filter
es un lugar adecuado para esto. Puede capturar el cuerpo de la respuesta reemplazando el ServletResponse
pasado con una implementación HttpServletResponseWrapper
que reemplaza el HttpServletResponse#getWriter()
con una implementación propia que copia el cuerpo de la respuesta en un búfer. Después de continuar la cadena de filtro con la respuesta reemplazada, solo registre la copia.
Aquí está un ejemplo patada de cómo el método doFilter()
puede verse como:
public void doFilter(ServletRequest request, final ServletResponse response, FilterChain chain) throws IOException, ServletException {
final CopyPrintWriter writer = new CopyPrintWriter(response.getWriter());
chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
@Override public PrintWriter getWriter() {
return writer;
}
});
logger.log(writer.getCopy());
}
Así es como el CopyPrintWriter
puede verse como:
public class CopyPrintWriter extends PrintWriter {
private StringBuilder copy = new StringBuilder();
public CopyPrintWriter(Writer writer) {
super(writer);
}
@Override
public void write(int c) {
copy.append((char) c); // It is actually a char, not an int.
super.write(c);
}
@Override
public void write(char[] chars, int offset, int length) {
copy.append(chars, offset, length);
super.write(chars, offset, length);
}
@Override
public void write(String string, int offset, int length) {
copy.append(string, offset, length);
super.write(string, offset, length);
}
public String getCopy() {
return copy.toString();
}
}
Ubicación del filtro en una url-pattern
para el que desea para registrar respuestas para. Tenga en cuenta que el contenido binario/estático como imágenes, CSS, archivos JS, etc. no se registrará de esta manera. Desea excluirlos mediante el uso de un número suficientemente específico url-pattern
, p. Ej. *.jsp
o simplemente en el servlet-name
del servlet en cuestión. Si desea registrar contenido binario/estático de todos modos (para lo cual no veo ningún beneficio), entonces necesita reemplazar el HttpServletResponse#getOutputStream()
de la misma manera también.
Tal vez un servlet filter puede ayudarlo. Piense en ello como una programación orientada a aspectos para HTTP.
Una alternativa a BalusC answer Usando el TeeOutputStream para escribir en dos salidas en el tiempo.
public void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(baos);
chain.doFilter(req,new HttpServletResponseWrapper(res) {
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new DelegatingServletOutputStream(new TeeOutputStream(super.getOutputStream(), ps)
);
}
@Override
public PrintWriter getWriter() throws IOException {
return new PrintWriter(new DelegatingServletOutputStream (new TeeOutputStream(super.getOutputStream(), ps))
);
}
});
//Get Response body calling baos.toString();
}
Para el beneficio de las generaciones futuras ... ¿de qué bibliotecas son 'TeeOutputStream' y' DelegatingServletOutputStream'? –
Es de primavera y apache io. 1) https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/mock/web/DelegatingServletOutputStream.html 2) https://commons.apache.org/proper/commons-io /javadocs/api-1.4/org/apache/commons/io/output/TeeOutputStream.html – Happier
Realizo una versión OutputStream sin dependencia de terceros, similar con @pdorgambide. Puede encontrarlo en this link.
- 1. ¿Cómo capturar y registrar mejor la salida de scp?
- 2. Lea el cuerpo de respuesta en un Android Spring Interceptor
- 3. conseguir el cuerpo de la respuesta de HttpResponse
- 4. La respuesta de falla de HTTP sobrescribe el cuerpo de respuesta para clientes no locales
- 5. Cuerpo de respuesta de escritura con BaseHTTPRequestHandler
- 6. servicio web WCF: la respuesta es 200/ok, pero el cuerpo de respuesta está vacío
- 7. ¿Obtienes todo el cuerpo de respuesta cuando la respuesta se fragmenta?
- 8. Leer cuerpo de la respuesta de error en Java
- 9. ¿Puedo usar tcpdump para obtener solicitudes HTTP, encabezado de respuesta y cuerpo de respuesta?
- 10. C# - Obtener el cuerpo de la respuesta de un error 403
- 11. Problema Unicode Node.js con el cuerpo de respuesta HTTP
- 12. JMeter: ¿cómo registrar la solicitud completa de una respuesta fallida?
- 13. cuerpo de la respuesta AJAX para su uso en respuesta de error
- 14. Capturar respuesta a "La aplicación desea enviarle notificaciones push" alerta
- 15. Necesita cuerpo de respuesta de HTTP 500 con file_get_contents (PHP)
- 16. Mod de respuesta de seguridad/tamaño del cuerpo de solicitud?
- 17. ¿No está obteniendo el cuerpo de respuesta para la solicitud de http en android?
- 18. Respuesta REST: ¿debo poner la URL del nuevo recurso en el encabezado, el cuerpo o ambos?
- 19. ¿Se permite enviar una respuesta HTTP POST a un cuerpo de respuesta?
- 20. Capturar respuesta a una prueba de soapUI ejecutar
- 21. Cómo capturar datos completos de solicitud HTTP (encabezados y cuerpo) con PHP?
- 22. WARN No se pudo determinar la longitud del contenido del cuerpo de la respuesta. Conjunto de longitud de contenido de la respuesta o conjunto de Respuesta # fragmentada = true
- 23. Error al deserializar el cuerpo del mensaje de respuesta para la operación
- 24. Cuerpo de respuesta de registro (HTML) de HttpServletResponse utilizando Spring MVC HandlerInterceptorAdapter
- 25. nginx: ¿Es posible capturar encabezados de respuesta en el registro de acceso cuando se usa nginx como un proxy inverso?
- 26. WebException cómo obtener una respuesta completa con un cuerpo?
- 27. Cómo capturar el evento System.exit?
- 28. de ignición y capturar eventos personalizados
- 29. ¿Cómo recupero el código de estado HTTP y el cuerpo de respuesta cuando se lanza una RestClientException?
- 30. ¿Cómo extraer el cuerpo de respuesta HTTP de una llamada de solicitud de Python?
Debe reemplazar no solo 'getWriter()', pero también 'getOutputStream()' – pihentagy
¿Qué hay de los problemas de codificación? – pihentagy
@pihentagy: 1) Si es necesario. 2) Use lo mismo que se establece mediante el método 'setCharacterEncoding()'. – BalusC