简体   繁体   中英

Is it possible to read the body of a response in spring boot?

I have a PrintWriter from an HttpServletResponse and I would like to know if there is any way to read its buffer (considering the HttpServletResponse.getWriter() PrintWriter isn't auto-flushed).

I know there are some ways to transform an InputStream to an OutputStream through InputStream.transferTo() but is there any way to do it in the other way and to convert my PrintWriter to any type of OutputStream? Or is there any way just to read the response body of an HttpServletResponse ?

So far I've tried the toString() method which is not overwritten. I tried to pipe it through different streams like PipedInputStream and ByteArrayOutputStream .

I'm using spring boot microservices architecture btw.

I finally found a way to handle this through spring boot Filter by overriding HttpServletResponseWrapper . so here's my code (the class that overrides the HttpServletResponseWrapper to change the response default output stream to my custom ServletOutputStream ):

public class HttpServletResponseCopier extends HttpServletResponseWrapper {

    private ServletOutputStreamCopier copier;
    private ServletOutputStream outputStream;
    private PrintWriter writer;

    /**
     * @param response
     */
    public HttpServletResponseCopier(HttpServletResponse response) {
        super(response);
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException
    {
        if (outputStream != null)
            throw new IOException("output stream already called for this response");
        else {
            outputStream = getResponse().getOutputStream();
            copier = new ServletOutputStreamCopier(this.outputStream);
            return copier;
        }
    }

    @Override
    public PrintWriter getWriter() throws IOException
    {
        if (outputStream != null)
            throw new IOException("print writer already called for this response");
        else {
            outputStream = getResponse().getOutputStream();
            copier = new ServletOutputStreamCopier(outputStream);
            writer = new PrintWriter(new OutputStreamWriter(copier, getResponse().getCharacterEncoding()));
            return writer;
        }
    }

    @Override
    public void flushBuffer() throws IOException
    {
        if (writer != null)
            writer.flush();
        else if (copier != null)
            copier.flush();

    }

    public String getContent()
    {
        String content = "";
        try {
            content = IOUtils.toString(copier.getCopyBuffer(), getResponse().getCharacterEncoding());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }

}

and my ServletOutputStreamCopier class (the class that copies the content of the stream into a ByteArrayOutputStream ):

public class ServletOutputStreamCopier extends ServletOutputStream {

    private ServletOutputStream outputStream;
    private ByteArrayOutputStream copier;

    /**
     * 
     */
    public ServletOutputStreamCopier(ServletOutputStream outputStream) {
        super();
        this.outputStream = outputStream;
        this.copier = new ByteArrayOutputStream();
    }

    @Override
    public boolean isReady()
    {
        return this.outputStream.isReady();
    }

    @Override
    public void setWriteListener(WriteListener listener)
    {

    }

    @Override
    public void write(int b) throws IOException
    {
        if (this.copier == null)
            this.copier = new ByteArrayOutputStream();
        if (this.outputStream == null)
            throw new IOException("outputStream is null");
        this.copier.write(b);
        this.outputStream.write(b);

    }

    public byte[] getCopyBuffer()
    {
        return this.copier.toByteArray();
    }

}

and finally inject it into the spring boot filter:

@Component
public class LoggingFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(
        HttpServletRequest request,
        HttpServletResponse response,
        FilterChain filterChain
    ) throws ServletException, IOException
    {
        HttpServletResponseCopier responseWrapper = new HttpServletResponseCopier(response);
        filterChain.doFilter(request, responseWrapper);

        System.out.println("response body: "+responseWrapper.getContent());

    }
}

which outputs this:

"body": <response body here>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM