Capture and record response body

I have a servlet that processes certain HTTP requests and responses. I want to register the response body before sending it back to the client. Is there a way I can capture the body of the response before it is sent as an HttpServletResponse object from the servlet?

+19
java servlets
Jul 13 '10 at 23:06
source share
4 answers

If I understand you correctly, do you want to register the response body ? This is quite an expensive task, but if it is a business requirement ...

As shown in the figure, a Filter is the right place for this. You can capture the response body by replacing the passed ServletResponse with HttpServletResponseWrapper , which replaces HttpServletResponse#getWriter() its own implementation, which copies the response body to some buffer. After continuing the filter circuit with the replaced answer, just write a copy.

Here's an example of how the doFilter() method looks like:

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

Here's what CopyPrintWriter looks CopyPrintWriter :

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

Match this filter to the url-pattern for which you want to register responses. Keep in mind that binary / static content, such as images, CSS, JS files, etc., will not be logged this way. You want to exclude them using a fairly specific url-pattern value, for example. *.jsp or only on the servlet-name the servlet in question. If you want to write binary / static content anyway (for which I see no use), you need to replace HttpServletResponse#getOutputStream() .

+25
Jul 14 2018-10-10T00:
source share

A servlet filter might help you. Think of it as aspect-oriented programming for HTTP.

+4
Jul 13 '10 at 23:30
source share

An alternative answer is BalusC Using a TeeOutputStream to write to two output streams at a point in time.

 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(); } 
+3
Feb 03 '15 at 17:27
source share

I am making a version of OutputStream without third-party dependencies similar to @pdorgambide. You can find in this link .

-one
Mar 12 '15 at 8:41
source share



All Articles