Last active
November 30, 2015 19:09
-
-
Save mikeapr4/4f96b6807585ad34813c to your computer and use it in GitHub Desktop.
Java Spring Filter for Caching response headers on static and non-static resources (see comment for details)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.springframework.util.AntPathMatcher; | |
import org.springframework.web.filter.GenericFilterBean; | |
import javax.servlet.FilterChain; | |
import javax.servlet.ServletException; | |
import javax.servlet.ServletRequest; | |
import javax.servlet.ServletResponse; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import java.io.IOException; | |
import java.util.LinkedHashMap; | |
/** | |
* Adds Caching response headers based on a request URL mapping. | |
* Each mapping is configured as FORCE_CHECK or NO_CACHE | |
*/ | |
public class CacheHeaderFilter extends GenericFilterBean { | |
private LinkedHashMap<String, CacheMode> cacheMap = new LinkedHashMap<>(); // sorted for pattern priority | |
private AntPathMatcher matcher = new AntPathMatcher(); | |
public CacheHeaderFilter(LinkedHashMap<String, CacheMode> cacheMap) { | |
this.cacheMap = cacheMap; | |
} | |
// Don't know what headers do what? | |
// https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers | |
public static void configCacheHeaders(CacheMode mode, HttpServletResponse res) { | |
switch (mode) { | |
case FORCE_CHECK: | |
res.setHeader("Cache-Control", "private, max-age=0"); | |
break; | |
case NO_CACHE: | |
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); | |
res.setHeader("Pragma", "no-cache"); | |
res.setDateHeader("Expires", 0); | |
break; | |
} | |
} | |
@Override | |
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) | |
throws IOException, ServletException { | |
String servletPath = ((HttpServletRequest) servletRequest).getServletPath(); | |
HttpServletResponse res = (HttpServletResponse) servletResponse; | |
for (String path : cacheMap.keySet()) { | |
if (matcher.match(path, servletPath)) { | |
configCacheHeaders(cacheMap.get(path), res); | |
break; | |
} | |
} | |
filterChain.doFilter(servletRequest, servletResponse); | |
} | |
public enum CacheMode {NO_CACHE, FORCE_CHECK} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Objective: Ensure that new content isn't ignored by the browser's in-built cache, but also to allow sensible caching to occur to avoid the application running sluggish.
When content is sent back to the browser, there are 2 possible instructions to send:
Content Classification
Static content includes:
Non-Static content includes:
Content Request-Response Flow
Further Reading
https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers
Static Content
First time, the browser requests the content (in this case the root page is a static index.html file)
Notice the response contains the last modified date of the content, this corresponds to the file modified date of the static resource, which suits. With the browser told it can cache (private), but with no allowance for stale content (max-age=0), the following request contains a predicate:
An alternative scenario is that the content has legitimately changed, meaning this happens:
Non-Static Content
First and all subsequent request/responses will look like this:
Sample Code Usage