public class ExpiresFilter extends FilterBase
 ExpiresFilter is a Java Servlet API port of Apache
 mod_expires to add 'Expires' and
 'Cache-Control: max-age=' headers to HTTP response according to its
 'Content-Type'.
 
Following documentation is inspired by mod_expires
 This filter controls the setting of the Expires HTTP header and the
 max-age directive of the Cache-Control HTTP header in
 server responses. The expiration date can set to be relative to either the
 time the source file was last modified, or to the time of the client access.
 
These HTTP headers are an instruction to the client about the document's validity and persistence. If cached, the document may be fetched from the cache rather than from the source until this time has passed. After that, the cache copy is considered "expired" and invalid, and a new copy must be obtained from the source.
 To modify Cache-Control directives other than max-age (see
 RFC
 2616 section 14.9), you can use other servlet filters or Apache Httpd
 mod_headers module.
 
Expires' and 'Cache-Control: max-age='
 headers to images, css and javascript
 <web-app ...>
    ...
    <filter>
       <filter-name>ExpiresFilter</filter-name>
       <filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
       <init-param>
          <param-name>ExpiresByType image</param-name>
          <param-value>access plus 10 minutes</param-value>
       </init-param>
       <init-param>
          <param-name>ExpiresByType text/css</param-name>
          <param-value>access plus 10 minutes</param-value>
       </init-param>
       <init-param>
          <param-name>ExpiresByType application/javascript</param-name>
          <param-value>access plus 10 minutes</param-value>
       </init-param>
    </filter>
    ...
    <filter-mapping>
       <filter-name>ExpiresFilter</filter-name>
       <url-pattern>/*</url-pattern>
       <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
    ...
 </web-app>
 
 
 ExpiresByType <content-type>
 This directive defines the value of the Expires header and the
 max-age directive of the Cache-Control header generated for
 documents of the specified type (e.g., text/html). The second
 argument sets the number of seconds that will be added to a base time to
 construct the expiration date. The Cache-Control: max-age is
 calculated by subtracting the request time from the expiration date and
 expressing the result in seconds.
 
 The base time is either the last modification time of the file, or the time
 of the client's access to the document. Which should be used is
 specified by the <code> field; M means that the
 file's last modification time should be used as the base time, and
 A means the client's access time should be used. The duration
 is expressed in seconds. A2592000 stands for
 access plus 30 days in alternate syntax.
 
 The difference in effect is subtle. If M (modification in
 alternate syntax) is used, all current copies of the document in all caches
 will expire at the same time, which can be good for something like a weekly
 notice that's always found at the same URL. If A (
 access or now in alternate syntax) is used, the date of
 expiration is different for each client; this can be good for image files
 that don't change very often, particularly for a set of related
 documents that all refer to the same images (i.e., the images will be
 accessed repeatedly within a relatively short timespan).
 
Example:
 <init-param>
    <param-name>ExpiresByType text/html</param-name>
    <param-value>access plus 1 month 15 days 2 hours</param-value>
 </init-param>
 <init-param>
    <!-- 2592000 seconds = 30 days -->
    <param-name>ExpiresByType image/gif</param-name>
    <param-value>A2592000</param-value>
 </init-param>
 
 
 
 Note that this directive only has effect if ExpiresActive On has
 been specified. It overrides, for the specified MIME type only, any
 expiration date set by the ExpiresDefault directive.
 
You can also specify the expiration time calculation using an alternate syntax, described earlier in this document.
ExpiresExcludedResponseStatusCodes
 This directive defines the http response status codes for which the
 ExpiresFilter will not generate expiration headers. By default, the
 304 status code ("Not modified") is skipped. The
 value is a comma separated list of http status codes.
 
 This directive is useful to ease usage of ExpiresDefault directive.
 Indeed, the behavior of 304 Not modified (which does specify a
 Content-Type header) combined with Expires and
 Cache-Control:max-age= headers can be unnecessarily tricky to
 understand.
 
Configuration sample :
 <init-param>
    <param-name>ExpiresExcludedResponseStatusCodes</param-name>
    <param-value>302, 500, 503</param-value>
 </init-param>
 
 
 
 This directive sets the default algorithm for calculating the expiration time
 for all documents in the affected realm. It can be overridden on a
 type-by-type basis by the ExpiresByType directive. See the
 description of that directive for details about the syntax of the argument,
 and the "alternate syntax" description as well.
 
 The ExpiresDefault and ExpiresByType directives can also be
 defined in a more readable syntax of the form:
 
 <init-param>
    <param-name>ExpiresDefault</param-name>
    <param-value><base> [plus] (<num> <type>)*</param-value>
 </init-param>
 <init-param>
    <param-name>ExpiresByType type/encoding</param-name>
    <param-value><base> [plus] (<num> <type>)*</param-value>
 </init-param>
 
 
 
 where <base> is one of:
 
accessnow (equivalent to 'access')modification
 The plus keyword is optional. <num> should be an
 integer value (acceptable to Integer.parseInt()), and
 <type> is one of:
 
yearsmonthsweeksdayshoursminutessecondsFor example, any of the following directives can be used to make documents expire 1 month after being accessed, by default:
 <init-param>
    <param-name>ExpiresDefault</param-name>
    <param-value>access plus 1 month</param-value>
 </init-param>
 <init-param>
    <param-name>ExpiresDefault</param-name>
    <param-value>access plus 4 weeks</param-value>
 </init-param>
 <init-param>
    <param-name>ExpiresDefault</param-name>
    <param-value>access plus 30 days</param-value>
 </init-param>
 
 
 
 The expiry time can be fine-tuned by adding several '
 <num> <type>' clauses:
 
 <init-param>
    <param-name>ExpiresByType text/html</param-name>
    <param-value>access plus 1 month 15 days 2 hours</param-value>
 </init-param>
 <init-param>
    <param-name>ExpiresByType image/gif</param-name>
    <param-value>modification plus 5 hours 3 minutes</param-value>
 </init-param>
 
 
 
 Note that if you use a modification date based setting, the Expires
 header will not be added to content that does not come from
 a file on disk. This is due to the fact that there is no modification time
 for such content.
 
 A response is eligible to be enriched by ExpiresFilter if :
 
Expires header or the
 max-age directive of the Cache-Control header),ExpiresExcludedResponseStatusCodes,Content-Type of the response matches one of the types
 defined the in ExpiresByType directives or the
 ExpiresDefault directive is defined.Note :
Cache-Control header contains other directives than
 max-age, they are concatenated with the max-age directive
 that is added by the ExpiresFilter.The expiration configuration if elected according to the following algorithm:
ExpiresByType matching the exact content-type returned by
 HttpServletResponse.getContentType() possibly including the charset
 (e.g. 'text/xml;charset=UTF-8'),ExpiresByType matching the content-type without the charset if
 HttpServletResponse.getContentType() contains a charset (e.g. '
 text/xml;charset=UTF-8' -> 'text/xml'),ExpiresByType matching the major type (e.g. substring before
 '/') of HttpServletResponse.getContentType()
 (e.g. 'text/xml;charset=UTF-8' -> 'text
 '),ExpiresDefault
 The ExpiresFilter traps the 'on before write response
 body' event to decide whether it should generate expiration headers or
 not.
 
 To trap the 'before write response body' event, the
 ExpiresFilter wraps the http servlet response's writer and
 outputStream to intercept calls to the methods write(),
 print(), close() and flush(). For empty response
 body (e.g. empty files), the write(), print(),
 close() and flush() methods are not called; to handle this
 case, the ExpiresFilter, at the end of its doFilter()
 method, manually triggers the onBeforeWriteResponseBody() method.
 
 The ExpiresFilter supports the same configuration syntax as Apache
 Httpd mod_expires.
 
 A challenge has been to choose the name of the <param-name>
 associated with ExpiresByType in the <filter>
 declaration. Indeed, Several ExpiresByType directives can be
 declared when web.xml syntax does not allow to declare several
 <init-param> with the same name.
 
 The workaround has been to declare the content type in the
 <param-name> rather than in the <param-value>.
 
 The ExpiresFilter has been designed for extension following the
 open/close principle.
 
Key methods to override for extension are :
isEligibleToExpirationHeaderGeneration(HttpServletRequest, XHttpServletResponse)
 getExpirationDate(XHttpServletResponse)
 To troubleshoot, enable logging on the
 org.apache.catalina.filters.ExpiresFilter.
 
Extract of logging.properties
 org.apache.catalina.filters.ExpiresFilter.level = FINE
 
 Sample of initialization log message :
 Mar 26, 2010 2:01:41 PM org.apache.catalina.filters.ExpiresFilter init
 FINE: Filter initialized with configuration ExpiresFilter[
    excludedResponseStatusCode=[304],
    default=null,
    byType={
       image=ExpiresConfiguration[startingPoint=ACCESS_TIME, duration=[10 MINUTE]],
       text/css=ExpiresConfiguration[startingPoint=ACCESS_TIME, duration=[10 MINUTE]],
       application/javascript=ExpiresConfiguration[startingPoint=ACCESS_TIME, duration=[10 MINUTE]]}]
 
 
 Sample of per-request log message where ExpiresFilter adds an
 expiration date
 
 Mar 26, 2010 2:09:47 PM org.apache.catalina.filters.ExpiresFilter onBeforeWriteResponseBody
 FINE: Request "/tomcat.gif" with response status "200" content-type "image/gif", set expiration date 3/26/10 2:19 PM
 
 
 Sample of per-request log message where ExpiresFilter does not add
 an expiration date
 
 Mar 26, 2010 2:10:27 PM org.apache.catalina.filters.ExpiresFilter onBeforeWriteResponseBody
 FINE: Request "/docs/config/manager.html" with response status "200" content-type "text/html", no expiration configured
 | Modifier and Type | Class and Description | 
|---|---|
| protected static class  | ExpiresFilter.DurationDuration composed of an  ExpiresFilter.Duration.amountand aExpiresFilter.Duration.unit | 
| protected static class  | ExpiresFilter.DurationUnitDuration unit | 
| protected static class  | ExpiresFilter.ExpiresConfiguration
 Main piece of configuration of the filter. | 
| protected static class  | ExpiresFilter.StartingPointExpiration configuration starting point. | 
| class  | ExpiresFilter.XHttpServletResponse
 Wrapping extension of the  HttpServletResponseto yrap the
 "Start Write Response Body" event. | 
| class  | ExpiresFilter.XPrintWriterWrapping extension of  PrintWriterto trap the
 "Start Write Response Body" event. | 
| class  | ExpiresFilter.XServletOutputStreamWrapping extension of  ServletOutputStreamto trap the
 "Start Write Response Body" event. | 
sm| Constructor and Description | 
|---|
| ExpiresFilter() | 
| Modifier and Type | Method and Description | 
|---|---|
| protected static int[] | commaDelimitedListToIntArray(String commaDelimitedInts)Convert a comma delimited list of numbers into an  int[]. | 
| protected static String[] | commaDelimitedListToStringArray(String commaDelimitedStrings)Convert a given comma delimited list of strings into an array of String | 
| protected static boolean | contains(String str,
        String searchStr) | 
| void | doFilter(ServletRequest request,
        ServletResponse response,
        FilterChain chain)The  doFiltermethod of the Filter is called by the container
 each time a request/response pair is passed through the chain due to a
 client request for a resource at the end of the chain. | 
| ExpiresFilter.ExpiresConfiguration | getDefaultExpiresConfiguration() | 
| String | getExcludedResponseStatusCodes() | 
| int[] | getExcludedResponseStatusCodesAsInts() | 
| protected Date | getExpirationDate(ExpiresFilter.ExpiresConfiguration configuration,
                 ExpiresFilter.XHttpServletResponse response)
 Returns the expiration date of the given  ExpiresFilter.ExpiresConfiguration,HttpServletRequestandExpiresFilter.XHttpServletResponse. | 
| protected Date | getExpirationDate(ExpiresFilter.XHttpServletResponse response)
 Returns the expiration date of the given  ExpiresFilter.XHttpServletResponseornullif no expiration date has been configured for the
 declared content type. | 
| Map<String,ExpiresFilter.ExpiresConfiguration> | getExpiresConfigurationByContentType() | 
| protected Log | getLogger() | 
| void | init(FilterConfig filterConfig)Iterates over the configuration parameters and either logs a warning,
 or throws an exception for any parameter that does not have a matching
 setter in this filter. | 
| protected static String | intsToCommaDelimitedString(int[] ints)Convert an array of ints into a comma delimited string | 
| protected boolean | isEligibleToExpirationHeaderGeneration(HttpServletRequest request,
                                      ExpiresFilter.XHttpServletResponse response)protectedfor extension. | 
| protected static boolean | isEmpty(String str) | 
| protected static boolean | isNotEmpty(String str) | 
| void | onBeforeWriteResponseBody(HttpServletRequest request,
                         ExpiresFilter.XHttpServletResponse response)
 If no expiration header has been set by the servlet and an expiration has
 been defined in the  ExpiresFilterconfiguration, sets the
 'Expires' header and the attribute 'max-age' of the
 'Cache-Control' header. | 
| protected ExpiresFilter.ExpiresConfiguration | parseExpiresConfiguration(String inputLine)Parse configuration lines like
 ' access plus 1 month 15 days 2 hours' or
 'modification 1 day 2 hours 5 seconds' | 
| void | setDefaultExpiresConfiguration(ExpiresFilter.ExpiresConfiguration defaultExpiresConfiguration) | 
| void | setExcludedResponseStatusCodes(int[] excludedResponseStatusCodes) | 
| void | setExpiresConfigurationByContentType(Map<String,ExpiresFilter.ExpiresConfiguration> expiresConfigurationByContentType) | 
| protected static boolean | startsWithIgnoreCase(String string,
                    String prefix) | 
| protected static String | substringBefore(String str,
               String separator) | 
| String | toString() | 
destroy, isConfigProblemFatalprotected static int[] commaDelimitedListToIntArray(String commaDelimitedInts)
int[].commaDelimitedInts - can be nullnull arrayprotected static String[] commaDelimitedListToStringArray(String commaDelimitedStrings)
commaDelimitedStrings - the string to be splitnull)protected static boolean contains(String str, String searchStr)
str - String that will be searchedsearchStr - The substring to searchtrue if the given str contains the given
 searchStr.protected static String intsToCommaDelimitedString(int[] ints)
ints - The int arrayprotected static boolean isEmpty(String str)
str - The String to checktrue if the given str is
 null or has a zero characters length.protected static boolean isNotEmpty(String str)
str - The String to checktrue if the given str has at least one
 character (can be a withespace).protected static boolean startsWithIgnoreCase(String string, String prefix)
string - can be nullprefix - can be nulltrue if the given string starts with the
 given prefix ignoring case.protected static String substringBefore(String str, String separator)
str - can be nullseparator - can be nullstr that is before the first
 occurrence of the given separator. Return null
 if the given str or the given separator is
 null. Return and empty string if the separator is empty.public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
FilterdoFilter method of the Filter is called by the container
 each time a request/response pair is passed through the chain due to a
 client request for a resource at the end of the chain. The FilterChain
 passed in to this method allows the Filter to pass on the request and
 response to the next entity in the chain.
 
 A typical implementation of this method would follow the following
 pattern:- 
 1. Examine the request
 2. Optionally wrap the request object with a custom implementation to
 filter content or headers for input filtering 
 3. Optionally wrap the response object with a custom implementation to
 filter content or headers for output filtering 
 4. a) Either invoke the next entity in the chain using
 the FilterChain object (chain.doFilter()), 
 4. b) or not pass on the request/response pair to the
 next entity in the filter chain to block the request processing
 5. Directly set headers on the response after invocation of the next
 entity in the filter chain.
request - The request to processresponse - The response associated with the requestchain - Provides access to the next filter in the chain for this
                 filter to pass the request and response to for further
                 processingIOException - if an I/O error occurs during this filter's
                     processing of the requestServletException - if the processing fails for any other reasonpublic ExpiresFilter.ExpiresConfiguration getDefaultExpiresConfiguration()
public String getExcludedResponseStatusCodes()
public int[] getExcludedResponseStatusCodesAsInts()
protected Date getExpirationDate(ExpiresFilter.XHttpServletResponse response)
 Returns the expiration date of the given ExpiresFilter.XHttpServletResponse or
 null if no expiration date has been configured for the
 declared content type.
 
 protected for extension.
 
response - The Servlet responseServletResponse.getContentType()protected Date getExpirationDate(ExpiresFilter.ExpiresConfiguration configuration, ExpiresFilter.XHttpServletResponse response)
 Returns the expiration date of the given ExpiresFilter.ExpiresConfiguration,
 HttpServletRequest and ExpiresFilter.XHttpServletResponse.
 
 protected for extension.
 
configuration - The parsed expiresresponse - The Servlet responsepublic Map<String,ExpiresFilter.ExpiresConfiguration> getExpiresConfigurationByContentType()
protected Log getLogger()
getLogger in class FilterBasepublic void init(FilterConfig filterConfig) throws ServletException
FilterBaseinit in interface Filterinit in class FilterBasefilterConfig - The configuration information associated with the
                     filter instance being initialisedServletException - if FilterBase.isConfigProblemFatal() returns
                          true and a configured parameter does not
                          have a matching setterprotected boolean isEligibleToExpirationHeaderGeneration(HttpServletRequest request, ExpiresFilter.XHttpServletResponse response)
 protected for extension.
 
request - The Servlet requestresponse - The Servlet responsetrue if an expire header may be addedpublic void onBeforeWriteResponseBody(HttpServletRequest request, ExpiresFilter.XHttpServletResponse response)
 If no expiration header has been set by the servlet and an expiration has
 been defined in the ExpiresFilter configuration, sets the
 'Expires' header and the attribute 'max-age' of the
 'Cache-Control' header.
 
Must be called on the "Start Write Response Body" event.
 Invocations to Logger.debug(...) are guarded by
 Log.isDebugEnabled() because
 HttpServletRequest.getRequestURI() and
 ServletResponse.getContentType() costs String
 objects instantiations (as of Tomcat 7).
 
request - The Servlet requestresponse - The Servlet responseprotected ExpiresFilter.ExpiresConfiguration parseExpiresConfiguration(String inputLine)
access plus 1 month 15 days 2 hours' or
 'modification 1 day 2 hours 5 seconds'inputLine - the inputpublic void setDefaultExpiresConfiguration(ExpiresFilter.ExpiresConfiguration defaultExpiresConfiguration)
public void setExcludedResponseStatusCodes(int[] excludedResponseStatusCodes)
public void setExpiresConfigurationByContentType(Map<String,ExpiresFilter.ExpiresConfiguration> expiresConfigurationByContentType)
Copyright © 2000-2020 Apache Software Foundation. All Rights Reserved.