Class CachingHttpServletResponse

java.lang.Object
jakarta.servlet.ServletResponseWrapper
jakarta.servlet.http.HttpServletResponseWrapper
org.apache.juneau.rest.server.util.CachingHttpServletResponse
All Implemented Interfaces:
jakarta.servlet.http.HttpServletResponse, jakarta.servlet.ServletResponse

public class CachingHttpServletResponse extends jakarta.servlet.http.HttpServletResponseWrapper
Wraps an HttpServletResponse and tees a bounded copy of the output stream into memory for debug logging.

At most a configured cap (default 8 KB) of the response body is captured while all bytes are still written through to the real client. The total number of bytes written is tracked so a truncation marker can be rendered.

The underlying ServletResponse.getOutputStream() is not acquired until the first getOutputStream() or getWriter() call — acquiring it eagerly in the constructor would permanently lock the response into stream mode, making a subsequent direct getWriter() call on this wrapper (or on the underlying response) throw IllegalStateException per the servlet spec, even for calls that never write anything.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    Default body capture cap, in bytes (8 KB).

    Fields inherited from interface jakarta.servlet.http.HttpServletResponse

    SC_ACCEPTED, SC_BAD_GATEWAY, SC_BAD_REQUEST, SC_CONFLICT, SC_CONTINUE, SC_CREATED, SC_EXPECTATION_FAILED, SC_FORBIDDEN, SC_FOUND, SC_GATEWAY_TIMEOUT, SC_GONE, SC_HTTP_VERSION_NOT_SUPPORTED, SC_INTERNAL_SERVER_ERROR, SC_LENGTH_REQUIRED, SC_METHOD_NOT_ALLOWED, SC_MISDIRECTED_REQUEST, SC_MOVED_PERMANENTLY, SC_MOVED_TEMPORARILY, SC_MULTIPLE_CHOICES, SC_NO_CONTENT, SC_NON_AUTHORITATIVE_INFORMATION, SC_NOT_ACCEPTABLE, SC_NOT_FOUND, SC_NOT_IMPLEMENTED, SC_NOT_MODIFIED, SC_OK, SC_PARTIAL_CONTENT, SC_PAYMENT_REQUIRED, SC_PERMANENT_REDIRECT, SC_PRECONDITION_FAILED, SC_PROXY_AUTHENTICATION_REQUIRED, SC_REQUEST_ENTITY_TOO_LARGE, SC_REQUEST_TIMEOUT, SC_REQUEST_URI_TOO_LONG, SC_REQUESTED_RANGE_NOT_SATISFIABLE, SC_RESET_CONTENT, SC_SEE_OTHER, SC_SERVICE_UNAVAILABLE, SC_SWITCHING_PROTOCOLS, SC_TEMPORARY_REDIRECT, SC_UNAUTHORIZED, SC_UNPROCESSABLE_CONTENT, SC_UNSUPPORTED_MEDIA_TYPE, SC_UPGRADE_REQUIRED, SC_USE_PROXY
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    protected
    CachingHttpServletResponse(jakarta.servlet.http.HttpServletResponse res, int cap)
    Constructor.
  • Method Summary

    Modifier and Type
    Method
    Description
    byte[]
    Returns the captured (possibly truncated) response body bytes.
    jakarta.servlet.ServletOutputStream
     
    long
    Returns the total number of body bytes written so far, including any bytes beyond the capture cap.
    Returns a character-stream tee that writes through getOutputStream().
    wrap(jakarta.servlet.http.HttpServletResponse res)
    Wraps the specified response inside a CachingHttpServletResponse if it isn't already, using the default cap.
    wrap(jakarta.servlet.http.HttpServletResponse res, int cap)
    Wraps the specified response inside a CachingHttpServletResponse if it isn't already.

    Methods inherited from class jakarta.servlet.http.HttpServletResponseWrapper

    addCookie, addDateHeader, addHeader, addIntHeader, containsHeader, encodeRedirectURL, encodeURL, getHeader, getHeaderNames, getHeaders, getStatus, getTrailerFields, sendError, sendError, sendRedirect, sendRedirect, sendRedirect, sendRedirect, setDateHeader, setHeader, setIntHeader, setStatus, setTrailerFields

    Methods inherited from class jakarta.servlet.ServletResponseWrapper

    flushBuffer, getBufferSize, getCharacterEncoding, getContentType, getLocale, getResponse, isCommitted, isWrapperFor, isWrapperFor, reset, resetBuffer, setBufferSize, setCharacterEncoding, setCharacterEncoding, setContentLength, setContentLengthLong, setContentType, setLocale, setResponse

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface jakarta.servlet.ServletResponse

    flushBuffer, getBufferSize, getCharacterEncoding, getContentType, getLocale, isCommitted, reset, resetBuffer, setBufferSize, setCharacterEncoding, setCharacterEncoding, setContentLength, setContentLengthLong, setContentType, setLocale
  • Field Details

  • Constructor Details

    • CachingHttpServletResponse

      protected CachingHttpServletResponse(jakarta.servlet.http.HttpServletResponse res, int cap)
      Constructor.
      Parameters:
      res - The wrapped servlet response. Must not be null.
      cap - The maximum number of body bytes to capture.
  • Method Details

    • wrap

      public static CachingHttpServletResponse wrap(jakarta.servlet.http.HttpServletResponse res)
      Wraps the specified response inside a CachingHttpServletResponse if it isn't already, using the default cap.
      Parameters:
      res - The response to wrap. Must not be null.
      Returns:
      The wrapped response.
    • wrap

      public static CachingHttpServletResponse wrap(jakarta.servlet.http.HttpServletResponse res, int cap)
      Wraps the specified response inside a CachingHttpServletResponse if it isn't already.
      Parameters:
      res - The response to wrap. Must not be null.
      cap - The maximum number of body bytes to capture.
      Returns:
      The wrapped response.
    • getContent

      public byte[] getContent()
      Returns the captured (possibly truncated) response body bytes.
      Returns:
      The captured body bytes (at most the configured cap). Never null.
    • getTotalLength

      public long getTotalLength()
      Returns the total number of body bytes written so far, including any bytes beyond the capture cap.
      Returns:
      The total body length in bytes.
    • getOutputStream

      public jakarta.servlet.ServletOutputStream getOutputStream() throws IOException
      Specified by:
      getOutputStream in interface jakarta.servlet.ServletResponse
      Overrides:
      getOutputStream in class jakarta.servlet.ServletResponseWrapper
      Throws:
      IOException
    • getWriter

      Returns a character-stream tee that writes through getOutputStream().

      Juneau's own RestResponse.getWriter() always negotiates its writer over getOutputStream(), so this override chiefly protects direct/raw consumers (filters, non-Juneau servlets in the same chain) that call HttpServletResponse.getWriter() on the wrapped response after capture has been installed — without it, that call would either bypass the tee entirely or throw IllegalStateException because getOutputStream() may have already been called.

      Specified by:
      getWriter in interface jakarta.servlet.ServletResponse
      Overrides:
      getWriter in class jakarta.servlet.ServletResponseWrapper
      Throws:
      IOException