Class BodyCapturingFilter
- java.lang.Object
-
- com.github.robtimus.servlet.http.BodyCapturingFilter
-
- All Implemented Interfaces:
Filter
public abstract class BodyCapturingFilter extends Object implements Filter
A filter that captures request and response bodies. When the request body is fully read,onBodyCaptured(BodyCapturingRequest)
is called. When the response is complete,onBodyCaptured(BodyCapturingResponse, HttpServletRequest)
is called. Both methods can be overridden to perform the necessary logic, for example logging the request and/or response.If the request body is not fully read, by default
onBodyCaptured(BodyCapturingRequest)
is never called. This can be the case if none of the downstream filters and servlets fully consumes the request's body. This is the default setting for some frameworks. For instance, some JSON parsers stop reading as soon as the root object's closing curly brace is encountered. Ideally the framework should be configured to consume all content (for custom filters and servletsensureBodyConsumed(HttpServletRequest, boolean)
is available). If that's not possible, the following initialization parameters are available to attempt to ensureonBodyCaptured(BodyCapturingRequest)
is still called:Name Type Description Default considerRequestReadAfterContentLength boolean true
to consider the request body as fully read once the number of bytes or characters specified in theContent-Length
header has been reached.false
ensureRequestBodyConsumed boolean true
to ensure that the request body is consumed. This is be done after the response has been completed. This means that if the request body has not been consumed already,onBodyCaptured(BodyCapturingRequest)
will be called just beforeonBodyCaptured(BodyCapturingResponse, HttpServletRequest)
is called.false
Name Type Description Default initialRequestCapacity int The initial capacity for the buffer used for capturing a request's body; not negative. May be overridden on a per-request basis by initialRequestCapacity(HttpServletRequest)
.32
initialRequestCapacityFromContentLength boolean true
to use the request's content length for the initial capacity. Iftrue
, theinitialRequestCapacity
initialization parameter is ignored.false
requestLimit int The limit for the number of bytes or characters of a request's body to capture; not negative. May be overridden on a per-request basis by requestLimit(HttpServletRequest)
.Integer.MAX_VALUE
initialResponseCapacity int The initial capacity for the buffer used for capturing a response's body; not negative. May be overridden on a per-request basis by initialResponseCapacity(HttpServletRequest)
.32
responseLimit int The limit for the number of bytes or characters of a response's body to capture; not negative. May be overridden on a per-request basis by responseLimit(HttpServletRequest)
.Integer.MAX_VALUE
Note that
captureBody(HttpServletRequest)
can be used to completely turn off capturing a request's body; if this is the case,onBodyCaptured(BodyCapturingRequest)
is called immediately. To turn off capturing a response's body, set its limit to0
and ignore any call toonLimitReached(BodyCapturingResponse, HttpServletRequest)
.- Author:
- Rob Spoor
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description protected class
BodyCapturingFilter.BodyCapturingRequest
AnHttpServletRequest
wrapper that captures the request's body as it's read.protected class
BodyCapturingFilter.BodyCapturingResponse
AnHttpServletResponse
wrapper that captures the response's body as it's written.protected static class
BodyCapturingFilter.CaptureMode
The possible modes for capturing request and response bodies.
-
Constructor Summary
Constructors Constructor Description BodyCapturingFilter()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description protected boolean
captureBody(HttpServletRequest request)
Returns whether or not the body of a request should be captured.void
destroy()
void
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
static void
ensureBodyConsumed(HttpServletRequest request)
Ensures that the body of a request body is consumed.static void
ensureBodyConsumed(HttpServletRequest request, boolean preferReader)
Ensures that the body of a request body is consumed.protected boolean
hasNoBody(String method)
Returns whether or not an HTTP method has no body.void
init(FilterConfig filterConfig)
protected int
initialRequestCapacity(HttpServletRequest request)
Returns the initial capacity for the buffer used for capturing a request's body.protected int
initialResponseCapacity(HttpServletRequest request)
Returns the initial capacity for the buffer used for capturing a response's body.protected void
onBodyCaptured(BodyCapturingFilter.BodyCapturingRequest request)
Called when a request's body has been read.protected void
onBodyCaptured(BodyCapturingFilter.BodyCapturingResponse response, HttpServletRequest request)
Called when a response's body has been produced.protected void
onLimitReached(BodyCapturingFilter.BodyCapturingRequest request)
Called when the capture limit for a request's body is reached.protected void
onLimitReached(BodyCapturingFilter.BodyCapturingResponse response, HttpServletRequest request)
Called when the capture limit for a response's body is reached.protected int
requestLimit(HttpServletRequest request)
Returns the limit for the number of bytes or characters of a request's body to capture.protected int
responseLimit(HttpServletRequest request)
Returns the limit for the number of bytes or characters of a response's body to capture.
-
-
-
Method Detail
-
init
public void init(FilterConfig filterConfig)
-
doFilter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
- Specified by:
doFilter
in interfaceFilter
- Throws:
IOException
ServletException
-
captureBody
protected boolean captureBody(HttpServletRequest request)
Returns whether or not the body of a request should be captured.If this method returns
false
, thenonBodyCaptured(BodyCapturingRequest)
will be called immediately with a request for which the body will not have been captured. This prevents unnecessary capturing of the request body when it's not needed, e.g. because there is no request body.This implementation returns
false
if either of the following condition holds:- The
considerRequestReadAfterContentLength
initialization parameter istrue
and the request's content length is0
. hasNoBody(String)
returnstrue
.
- Parameters:
request
- The request for which to return whether or not the body should be captured.- Returns:
true
if the request's body should be captured, orfalse
otherwise.
- The
-
hasNoBody
protected boolean hasNoBody(String method)
Returns whether or not an HTTP method has no body. This method is used incaptureBody(HttpServletRequest)
to prevent capturing the request body when it's certain that there is no request body.This implementation returns whether or not the method is one of
GET
,DELETE
,OPTIONS
orHEAD
.- Parameters:
method
- The method to check.- Returns:
true
if the HTTP method has no body, orfalse
otherwise.
-
ensureBodyConsumed
public static void ensureBodyConsumed(HttpServletRequest request) throws IOException
Ensures that the body of a request body is consumed. This can be used in downstream filters or servlets to ensure thatonBodyCaptured(BodyCapturingRequest)
will be called.This method is shorthand for
ensureBodyConsumed(request, true)
.- Parameters:
request
- The request for which to ensure the request body is consumed.- Throws:
IOException
- If an I/O error occurs.
-
ensureBodyConsumed
public static void ensureBodyConsumed(HttpServletRequest request, boolean preferReader) throws IOException
Ensures that the body of a request body is consumed. This can be used in downstream filters or servlets to ensure thatonBodyCaptured(BodyCapturingRequest)
will be called.If
ServletRequest.getReader()
orServletRequest.getInputStream()
was already called on the request, then the request body is consumed using the same method (to prevent anyIllegalStateException
. Otherwise, thepreferReader
flag determines whether to useServletRequest.getReader()
(true
) orServletRequest.getInputStream()
(false
). Usetrue
if the request body is needed as a string (usingBodyCapturingFilter.BodyCapturingRequest.capturedTextBody()
), orfalse
if it's needed as bytes (usingBodyCapturingFilter.BodyCapturingRequest.capturedBinaryBody()
).- Parameters:
request
- The request for which to ensure the request body is consumed. This doesn't need to be aBodyCapturingFilter.BodyCapturingRequest
, it can also be a wrapper around the originalBodyCapturingFilter.BodyCapturingRequest
.preferReader
-true
to prefer usingServletRequest.getReader()
overServletRequest.getInputStream()
if neither was called before.- Throws:
IOException
- If an I/O error occurs.
-
onLimitReached
protected void onLimitReached(BodyCapturingFilter.BodyCapturingRequest request)
Called when the capture limit for a request's body is reached. This method will be called at most once for each request.This implementation does nothing.
- Parameters:
request
- The request for which the capture limit is reached.
-
onBodyCaptured
protected void onBodyCaptured(BodyCapturingFilter.BodyCapturingRequest request)
Called when a request's body has been read. This will be the case either if the request's body has been fullyconsumed
, or if itsinput stream
orreader
is closed. This method will be called at most once for each request.If all downstream filters and servlets fail to (completely) consume the request, this method will not be called by default. Set initialization parameter
ensureRequestBodyConsumed
totrue
to ensure that the request body is always consumed. This will be done after the response has been completed (but beforeonBodyCaptured(BodyCapturingResponse, HttpServletRequest)
is called).This implementation does nothing.
- Parameters:
request
- The request for which the body has been read.
-
onLimitReached
protected void onLimitReached(BodyCapturingFilter.BodyCapturingResponse response, HttpServletRequest request)
Called when the capture limit for a response's body is reached. This method will be called at most once for each response, unlessServletResponse.reset()
orServletResponse.resetBuffer()
is called on the response. For each call to either method, this method may be called at most once again.This implementation does nothing.
- Parameters:
response
- The response for which the capture limit is reached.request
- The request that lead to the response. This is provided to provide access to any request attributes.
-
onBodyCaptured
protected void onBodyCaptured(BodyCapturingFilter.BodyCapturingResponse response, HttpServletRequest request)
Called when a response's body has been produced. This method will be called exactly once for each response, regardless of any call toServletResponse.reset()
orServletResponse.resetBuffer()
.This implementation does nothing.
- Parameters:
response
- The response for which the body has been produced.request
- The request that lead to the response. This is provided to provide access to any request attributes.
-
initialRequestCapacity
protected int initialRequestCapacity(HttpServletRequest request)
Returns the initial capacity for the buffer used for capturing a request's body. This implementation will return the given request's content length if theinitialRequestCapacityFromContentLength
initialization parameter is set totrue
and the request has a content length defined. Otherwise it will return the value of theinitialRequestCapacity
initialization parameter. If that's not given,32
will be used.This method can be overridden to return something else depending on the request, for example based on the content type.
- Parameters:
request
- The request for which to return the initial buffer capacity.- Returns:
- The initial buffer capacity for the given request.
-
requestLimit
protected int requestLimit(HttpServletRequest request)
Returns the limit for the number of bytes or characters of a request's body to capture. This implementation will return the value of therequestLimit
initialization parameter.This method can be overridden to return something else depending on the request, for example based on the content type.
- Parameters:
request
- The request for which to return the capture limit.- Returns:
- The capture limit for the given request.
-
initialResponseCapacity
protected int initialResponseCapacity(HttpServletRequest request)
Returns the initial capacity for the buffer used for capturing a response's body. This implementation will return the value of theinitialResponseCapacity
initialization parameter. If that's not given,32
will be used.This method can be overridden to return something else depending on the request, for example based on the path. Since this method is called before the response is populated, the response cannot be used and is therefore not provided.
- Parameters:
request
- The request that leads to the response for which to return the initial buffer capacity.- Returns:
- The initial buffer capacity for the response to the given request.
-
responseLimit
protected int responseLimit(HttpServletRequest request)
Returns the limit for the number of bytes or characters of a response's body to capture. This implementation will return the value of theresponseLimit
initialization parameter.This method can be overridden to return something else depending on the request, for example based on the path. Since this method is called before the response is populated, the response cannot be used and is therefore not provided.
- Parameters:
request
- The request that leads to the response for which to return the capture limit.- Returns:
- The capture limit for the response to the given request.
-
-