Java Expiry Date header

Overview

One of the tricks to creating snappy and fast loading web pages is to set the correct ‘Expiry-date’ header on your web pages and static resources like images, CSS and Javascript files. By setting an expiration date in the future, you can tell the browser to cache the resource locally in the browser cache. This article discusses how to speed up your Java webapp by setting optimal expiration date to leverage browser caching.

An example of expiry date header is as follows:

Expires: Wed, 27 Oct 2010 19:02:24 EDT

The easiest way to set expiry date in Java webapps is via a servlet filter. Servlet filters are Java classes which extend the class javax.servlet.Filter. Servlet filters are an elegant way to intercept each request and do something useful, add a HTTP header in this case.

I wrote a Servlet filter which can be used to set the expiry date on any page in your webapp. You can use this servlet filter to set the expiry date header without writing any Java code in your project. You can also select which pages to set the expiry date and the age of the page via a properties file.

1. Download the code for expiration date filter and add it to your project

Download the file PageExpiryFilter.java and add it to your project.

2. Add a Servlet Filter to web.xml, and map it to all URLs

<filter>
 <filter-name>PageExpiryFilter</filter-name>
  <filter-class>com.vineetmanohar.web.PageExpiryFilter</filter-class>
 </filter>

 <filter-mapping>
  <filter-name>PageExpiryFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

3. Create ‘expires.property’ file in src/main/resources

Create the following file:

src/main/resources/expires.properties

You can set expiry date for all or some paths in your webapp by simply creating entries in this file

The format for each line is:

Format:
Resource Path = freshness interval for this resource

Pattern:
<full regex of the resource> = <number><unit>

Valid values for Unit:

  • m for minute
  • h for hour
  • d for day
  • w for week
  • M for month

Important

  1. Order in the properties file is important. The first rule which matches is applied and no more rules are checked.
  2. If no rules match, expiry date is not set.
  3. The path of the resource relative to the application root is matched against the regex. So if you app baseurl is http://foobar/somewebapp, the path for resource http://foobar/somewebapp/images/logo.png will be /images/logo.png.

Example 1:

^/css/.*  = 30d
^/js/.*   = 15d
^.*\.png$ = 2M
  • The first line specifies, all content starting with /css expires in 30 days from current date.
  • The second line specifies, all content starting with /js expires in 15 days from current date.
  • The third line specifies, all content ending with .png expires in 15 days from current date.
  • For those less familiar with regular expression, ^ denotes the beginning of the line and $ denotes the end of line. See full regex reference.

Example 2: For pages which don’t change a lot, you may want to set a smaller expiry date, says 4 hours. This is merely an example, you should examine the nature of your webapp before choosing the age of the page.

^/home/content/ = 4h

Example 3: Depending on how aggressive you want to be, you may want to set a default expiry date for all pages. This might not be suitable in all cases where pages change often and you want the browser to always load the latest page. Don’t use this if you don’t understand it completely.

.* = 1h

How to check Expiry Date header via a browser

Viewing Page Expiry Header in Firebug

Viewing HTTP Headers for www.cnn.com in Firebug

There are many tools that let you check HTTP header values. My personal favorite is Firebug, which is a Firefox plugin. Once you have firebug open, go to the “Net” console, and view your page. You should see a GET or POST request as a row on the console. Expand that row, and go to the “Headers” tab. You should see all the headers, including the “Expires” headers if present.

The following screenshot is Firefug’s Net console displaying HTTP headers from www.cnn.com. Notice that the expiry date is for www.cnn.com home page is only 1 minute. This lets the browser cache the page for 1 minute, and re-fetch the page after 1 minute. While this is suitable for cnn.com where content might change every minute, you should decide the expiry date for your website depending on how often the content changes.

I highly recommend getting Firebug and looking at the expiry date of your webapp. Firebug also shows what gets downloaded each time you request a page and what is loaded from cache. This may help you determine your requirements, for example, if you notice a static resource (javascript file or css file) getting downloaded in each request, you might want to add an expiry date header for that resource.

Conclusion

Setting an expiration date in the future lets user’s browser cache pages locally and results in fast loading pages and increased end user satisfaction. The technique described in this article lets Java webapps very easily set expiration date without writing any Java code. However, keep in mind that setting a long expiration date might not be the right thing to do in many cases, e.g. where freshness of content is important, or there are security implications.

References

Related posts:

  1. Cache Java webapps with Squid Reverse Proxy
  2. Access to www.w3.org DTDs blocked from Java
  3. Using Google Analytics Event API to track your website performance

8 comments to Java Expiry Date header

  • This has increased the load time of my website significantly. Thanks buddy.

  • vineet

    I hope you meant ‘decreased the load time’ and not ‘increased the load time’. Cheers.

  • AndrĂ© Pankraz

    Does’t work for none-US without setting Default Locale/Timezone.

    Fix:

    final Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.MINUTE, age);

    final DateFormat httpDateFormat = new SimpleDateFormat(
    “EEE, dd MMM yyyy HH:mm:ss z”, Locale.US);
    httpDateFormat.setTimeZone(TimeZone
    .getTimeZone(“GMT”));

    expiryDate = httpDateFormat.format(calendar
    .getTime());
    httpServletResponse
    .setHeader(“Expires”, expiryDate);

  • Rakesh

    Thanks for the code,I am using this code,application is running but when i look into the net console of firebug..it show
    1)Expires Thu Jan 01 1970 05:30:00 GMT+0530 (India Standard Time)

    It showing an old date ie 1970 …
    2)the logger prints : WARNING: No expiration date set for path: /Filter.jsp

    only thing different i m doing is int he web.xml

    PageExpiryFilter
    *.jsp
    *.html
    *.css
    *.jpg

    rest is same.
    What could be the reason.
    Thanks in advance.

  • Rakesh

    on more doubt vineet…where and when does the expires.property file come into play..? just needed the understanding.

  • vineet

    1) What are the contents of your expires.properties?

    2) What is the URL that you are accessing when you get the expires-header of ’1970′

    expires.properties is loaded by the PageExpiryFilter.java init() method.

  • Rakesh

    1)expires property file has:
    ^/css/.* = 30d
    ^.*\.jpg$ = 2M
    ^.*\.png$ = 2M
    ^.*\.gif$ = 2M
    ^/js/.* = 15d

    2)http://localhost:8080/TestApp/Testfilter.jsp
    For all new pages or old pages we are able to see the “Expires” field..how can we make sure our filter is working.?

  • vineet

    Rakesh, you need to add a row in expires.property as follows:
    /Testfilter.jsp = 1d

    This will set the expiry date to 1 day in the future.

    Check the logs to confirm whether the expiry date is set or not, if expiry is not set you will see log like this:
    WARNING: No expiration date set for path: /Filter.jsp

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Get Adobe Flash playerPlugin by wpburn.com wordpress themes