1
votes

The following is a snippet from the web.xml of my webapp

<filter>
   <filter-name>ExpiresFilter</filter-name>
   <filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
   <init-param>
      <param-name>ExpiresByType text/css</param-name>
      <param-value>access plus 3 months</param-value>
   </init-param>
   <init-param>
      <param-name>ExpiresByType text/html</param-name>
      <param-value>access plus 3 months</param-value>
   </init-param>
   <init-param>
      <param-name>ExpiresByType application/javascript</param-name>
      <param-value>access plus 3 months</param-value>
   </init-param>
</filter>
<filter-mapping>
   <filter-name>ExpiresFilter</filter-name>
   <url-pattern>/css/*</url-pattern>
   <url-pattern>/dist/*</url-pattern>
   <url-pattern>/lib/*</url-pattern>
   <url-pattern>/partials/*</url-pattern>
   <dispatcher>REQUEST</dispatcher>
</filter-mapping>

When turning the logging.properties to FINER i get

2015 11:51:35 AM org.apache.catalina.filters.ExpiresFilter isEligibleToExpirationHeaderGeneration FINE: Request "/kuku/dist/js/vendor.js.map" with response status "200" content-type "null", expiration header already defined

I searched in the conf directory of tomcat

grep -r expire conf

and did not find anything.

Where could the expiration header be set already?

4

4 Answers

1
votes

I don't know if it will help, but there actually two conditions under which you will get that log message:

  • if the response already has an "Expires" header

  • if the response has "Cache-control" header which specifies a "max-age" attribute.

Reference:

(I'm assuming I've found the correct source code ...)

1
votes

Update: This is somehow connected to the security.

I had the following xml snippet for authentication.

When removing it the expires header was set properly.

<security-constraint>
    <web-resource-collection>
        <web-resource-name>All</web-resource-name>
        <url-pattern>/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>kuku<role-name>
    </auth-constraint>

    <user-data-constraint>
        <!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->
        <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
</security-constraint>

<login-config>
    <auth-method>BASIC</auth-method>
</login-config>
<security-role>
<role-name>kuku</role-name>
</security-role>

The valve can be configured to allow caching https://tomcat.apache.org/tomcat-7.0-doc/config/valve.html#Basic_Authenticator_Valve

but it would be best to move away from this authentication scheme

0
votes

As stated by Stephen-C the org.apache.catalina.filters.ExpiresFilter will not work if something has already set Expires or Cache-Control: max-age headers.

This answer is to provide a workaround to those who like to fix this and also to thos who really want to understand this.

Here is a workaround:

public class MyExpiresFilter extends org.apache.catalina.filters.ExpiresFilter { @Override protected boolean isEligibleToExpirationHeaderGeneration( HttpServletRequest request, XHttpServletResponse response) { return true; } } and update your web.xml with this class MyExpiresFilter

<filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>

and make sure your war containts this compiled code or web context has this class in classpath.

0
votes

I know it is an old question, but since I struggled with this recently, here is some more information:

The "problem" is in org.apache.catalina.authenticator.AuthenticatorBase which sets an Expires header for secured resources (which makes sense). See e.g. (I only checked for Tomcat 7 and 8, but this is probably everywhere): https://github.com/Oreste-Luci/apache-tomcat-8.0.26-src/blob/master/java/org/apache/catalina/authenticator/AuthenticatorBase.java#L508-L518

The ExpiresFilter will not set header if the Expires header is present.

In my case I wanted to change the cache headers for a static resource, so I resorted to the meta HTML tag, more information at http://cristian.sulea.net/blog/disable-browser-caching-with-meta-html-tags/