Class ShallowEtagHeaderFilter

All Implemented Interfaces:
Filter, Aware, BeanNameAware, DisposableBean, InitializingBean, EnvironmentAware, EnvironmentCapable, ServletContextAware

public class ShallowEtagHeaderFilter extends OncePerRequestFilter
Filter that generates an ETag value based on the content on the response. This ETag is compared to the If-None-Match header of the request. If these headers are equal, the response content is not sent, but rather a 304 "Not Modified" status instead.

Since the ETag is based on the response content, the response (e.g. a View) is still rendered. As such, this filter only saves bandwidth, not server performance.

State-changing HTTP methods and other HTTP conditional request headers such as If-Match and If-Unmodified-Since are outside the scope of this filter. Please consider using ServletWebRequest.checkNotModified(String, long) instead.

Since:
3.0
Author:
Arjen Poutsma, Rossen Stoyanchev, Brian Clozel, Juergen Hoeller
  • Constructor Details

    • ShallowEtagHeaderFilter

      public ShallowEtagHeaderFilter()
  • Method Details

    • setWriteWeakETag

      public void setWriteWeakETag(boolean writeWeakETag)
      Set whether the ETag value written to the response should be weak, as per RFC 7232.

      Should be configured using an <init-param> for parameter name "writeWeakETag" in the filter definition in web.xml.

      Since:
      4.3
      See Also:
    • isWriteWeakETag

      public boolean isWriteWeakETag()
      Return whether the ETag value written to the response should be weak, as per RFC 7232.
      Since:
      4.3
    • shouldNotFilterAsyncDispatch

      protected boolean shouldNotFilterAsyncDispatch()
      The default value is false so that the filter may delay the generation of an ETag until the last asynchronously dispatched thread.
      Overrides:
      shouldNotFilterAsyncDispatch in class OncePerRequestFilter
    • doFilterInternal

      protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException
      Description copied from class: OncePerRequestFilter
      Same contract as for doFilter, but guaranteed to be just invoked once per request within a single request thread. See OncePerRequestFilter.shouldNotFilterAsyncDispatch() for details.

      Provides HttpServletRequest and HttpServletResponse arguments instead of the default ServletRequest and ServletResponse ones.

      Specified by:
      doFilterInternal in class OncePerRequestFilter
      Throws:
      ServletException
      IOException
    • isEligibleForEtag

      protected boolean isEligibleForEtag(HttpServletRequest request, HttpServletResponse response, int responseStatusCode, InputStream inputStream)
      Whether an ETag should be calculated for the given request and response exchange. By default, this is true if all the following match:
      • Response is not committed.
      • Response status codes is in the 2xx series.
      • Request method is a GET.
      • Response Cache-Control header does not contain "no-store" (or is not present at all).
      Parameters:
      request - the HTTP request
      response - the HTTP response
      responseStatusCode - the HTTP response status code
      inputStream - the response body
      Returns:
      true if eligible for ETag generation, false otherwise
    • generateETagHeaderValue

      protected String generateETagHeaderValue(InputStream inputStream, boolean isWeak) throws IOException
      Generate the ETag header value from the given response body byte array.

      The default implementation generates an MD5 hash.

      Parameters:
      inputStream - the response body as an InputStream
      isWeak - whether the generated ETag should be weak
      Returns:
      the ETag header value
      Throws:
      IOException
      See Also:
    • disableContentCaching

      public static void disableContentCaching(ServletRequest request)
      This method can be used to suppress the content caching response wrapper of the ShallowEtagHeaderFilter. The main reason for this is streaming scenarios which are not to be cached and do not need an eTag.

      Note: This method must be called before the response is written to in order for the entire response content to be written without caching.

      Since:
      4.2