Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixes #3 Optionally set expires header when cache control is applied …

…to a request.

Updated unit tests to cover expired headers.
  • Loading branch information...
commit 5e6dcefc110afe7ede8564dca0ccb45b9775f05b 1 parent a719155
@foo4u authored
View
146 spring-mvc-cache-control/src/main/java/net/rossillo/spring/web/mvc/CacheControlHandlerInterceptor.java
@@ -1,5 +1,9 @@
package net.rossillo.spring.web.mvc;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -19,6 +23,8 @@
private static final String HEADER_EXPIRES = "Expires";
private static final String HEADER_CACHE_CONTROL = "Cache-Control";
+ private boolean useExpiresHeader = true;
+
/**
* Creates a new cache control handler interceptor.
*/
@@ -38,69 +44,105 @@ protected final void assignCacheControlHeader(
final HttpServletResponse response,
final Object handler) {
- String cacheControl = this.cacheControl(request, response, handler);
+ final CacheControl cacheControl = this.getCacheControl(request, response, handler);
+ final String cacheControlHeader = this.createCacheControlHeader(cacheControl);
- if (cacheControl != null) {
- response.setHeader(HEADER_CACHE_CONTROL, cacheControl);
- /*
- if(response.containsHeader(HEADER_EXPIRES)) {
- response.setHeader(HEADER_EXPIRES, null);
+ if (cacheControlHeader != null) {
+ response.setHeader(HEADER_CACHE_CONTROL, cacheControlHeader);
+ if (useExpiresHeader) {
+ response.setDateHeader(HEADER_EXPIRES, createExpiresHeader(cacheControl));
}
- */
}
}
/**
- * Returns cache control header value for the given request, response
- * and handler.
+ * Returns cache control header value from the given {@link CacheControl}
+ * annotation.
*
- * @param request the <code>HttpServletRequest</code>
- * @param response the <code>HttpServletResponse</code>
- * @param handler the handler for the given <code>request</code>
+ * @param cacheControl the <code>CacheControl</code> annotation from which to
+ * create the returned cache control header value
*
* @return the cache control header value
*/
- protected final String cacheControl(
+ protected final String createCacheControlHeader(final CacheControl cacheControl) {
+
+ final StringBuilder builder = new StringBuilder();
+
+ if (cacheControl == null) {
+ return null;
+ }
+
+ final CachePolicy[] policies = cacheControl.policy();
+
+ if (cacheControl.maxAge() >= 0) {
+ builder.append("max-age=").append(cacheControl.maxAge());
+ }
+
+ if (cacheControl.sharedMaxAge() >= 0) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append("s-maxage=").append(cacheControl.sharedMaxAge());
+ }
+
+ if (policies != null) {
+ for (final CachePolicy policy : policies) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append(policy.policy());
+ }
+ }
+
+ return (builder.length() > 0 ? builder.toString() : null);
+ }
+
+ /**
+ * Returns an expires header value generated from the given
+ * {@link CacheControl} annotation.
+ *
+ * @param cacheControl the <code>CacheControl</code> annotation from which to
+ * create the returned expires header value
+ *
+ * @return the expires header value
+ */
+ protected final long createExpiresHeader(final CacheControl cacheControl) {
+
+ Calendar expires = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+
+ if (cacheControl.maxAge() >= 0) {
+ expires.add(Calendar.SECOND, cacheControl.maxAge());
+ }
+
+ return expires.getTime().getTime();
+ }
+
+ /**
+ * Returns the {@link CacheControl} annotation specified for the
+ * given request, response and handler.
+ *
+ * @param request the current <code>HttpServletRequest</code>
+ * @param response the current <code>HttpServletResponse</code>
+ * @param handler the current request handler
+ *
+ * @return the <code>CacheControl</code> annotation specified by
+ * the given <code>handler</code> if present; <code>null</code> otherwise
+ */
+ protected final CacheControl getCacheControl(
final HttpServletRequest request,
final HttpServletResponse response,
final Object handler) {
- final StringBuilder builder = new StringBuilder();
-
- if (handler != null && handler instanceof HandlerMethod) {
-
- final HandlerMethod handlerMethod = (HandlerMethod) handler;
- final CacheControl cacheControl = handlerMethod.getMethodAnnotation(CacheControl.class);
-
- if (cacheControl != null) {
-
- final CachePolicy[] policies = cacheControl.policy();
-
- if (cacheControl.maxAge() >= 0) {
- builder.append("max-age=").append(cacheControl.maxAge());
- }
-
- if (cacheControl.sharedMaxAge() >= 0) {
- if (builder.length() > 0) {
- builder.append(", ");
- }
- builder.append("s-maxage=").append(cacheControl.sharedMaxAge());
- }
-
- if (policies != null) {
- for (final CachePolicy policy : policies) {
- if (builder.length() > 0) {
- builder.append(", ");
- }
- builder.append(policy.policy());
- }
- }
- }
+ if (handler == null || !(handler instanceof HandlerMethod)) {
+ return null;
}
- return (builder.length() > 0 ? builder.toString() : null);
+ final HandlerMethod handlerMethod = (HandlerMethod) handler;
+ final CacheControl cacheControl = handlerMethod.getMethodAnnotation(CacheControl.class);
+
+ return cacheControl;
}
-
+
@Override
public final boolean preHandle(
final HttpServletRequest request,
@@ -111,4 +153,16 @@ public final boolean preHandle(
return super.preHandle(request, response, handler);
}
+
+ /**
+ * True to set an expires header when a {@link CacheControl} annotation is present
+ * on a handler; false otherwise. Defaults to true.
+ *
+ * @param useExpiresHeader <code>true</code> to set an expires header when a
+ * <code>CacheControl</code> annotation is present on a handler; <code>false</code> otherwise
+ */
+ public final void setUseExpiresHeader(final boolean useExpiresHeader) {
+ this.useExpiresHeader = useExpiresHeader;
+ }
+
}
View
4 spring-mvc-cache-control/src/test/java/net/rossillo/spring/web/mvc/CacheControlAnnotatedTestController.java
@@ -11,12 +11,12 @@ public String handlePubliclyCachedPageRequest() {
return null;
}
- @CacheControl(policy = { CachePolicy.PUBLIC, CachePolicy.MUST_REVALIDATE })
+ @CacheControl(policy = { CachePolicy.MUST_REVALIDATE }, maxAge = 300)
public String handlePubliclyCachedPageAndRevalidatedRequest() {
return null;
}
- @CacheControl(policy = { CachePolicy.PUBLIC, CachePolicy.PROXY_REVALIDATE })
+ @CacheControl(policy = { CachePolicy.PUBLIC, CachePolicy.PROXY_REVALIDATE }, maxAge = 60)
public String handlePubliclyCachedPageAndProxyRevalidatedRequest() {
return null;
}
View
46 spring-mvc-cache-control/src/test/java/net/rossillo/spring/web/mvc/CacheControlHandlerInterceptorTest.java
@@ -1,9 +1,10 @@
package net.rossillo.spring.web.mvc;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -17,11 +18,20 @@
*/
public final class CacheControlHandlerInterceptorTest {
- private CacheControlHandlerInterceptor interceptor = new CacheControlHandlerInterceptor();
+ private CacheControlHandlerInterceptor interceptor;
+
+ private MockHttpServletRequest request;
+
+ private MockHttpServletResponse response;
- private MockHttpServletRequest request = new MockHttpServletRequest();
- private MockHttpServletResponse response = new MockHttpServletResponse();
- private CacheControlAnnotatedTestController controller = new CacheControlAnnotatedTestController();
+ private final CacheControlAnnotatedTestController controller = new CacheControlAnnotatedTestController();
+
+ @Before
+ public void setUp() {
+ interceptor = new CacheControlHandlerInterceptor();
+ request = new MockHttpServletRequest();
+ response = new MockHttpServletResponse();
+ }
@Test
public void testCacheControlPublic() throws Exception {
@@ -57,7 +67,7 @@ public void testCacheControlPublicProxyMustRevalidate() throws Exception {
}
@Test
- public void testCacheControlPublicMustRevalidate() throws Exception {
+ public void testCacheControlMustRevalidate() throws Exception {
final HandlerMethod handler = new HandlerMethod(
controller,
@@ -68,7 +78,6 @@ public void testCacheControlPublicMustRevalidate() throws Exception {
System.err.println("CC: " + response.getHeader("Cache-Control"));
assertNotNull(response.getHeader("Cache-Control"));
- assertTrue(response.getHeader("Cache-Control").contains("public"));
assertTrue(response.getHeader("Cache-Control").contains("must-revalidate"));
assertFalse(response.getHeader("Cache-Control").contains("private"));
}
@@ -88,4 +97,27 @@ public void testCacheControlPrivate() throws Exception {
assertTrue(response.getHeader("Cache-Control").contains("private"));
assertFalse(response.getHeader("Cache-Control").contains("public"));
}
+
+ @Test
+ public void testExpires() throws Exception {
+
+ final HandlerMethod handler = new HandlerMethod(
+ controller,
+ controller.getClass().getMethod("handlePrivatelyCachedPageRequest"));
+
+ interceptor.preHandle(request, response, handler);
+ assertNotNull(response.getHeader("Expires"));
+ }
+
+ @Test
+ public void testNoExpires() throws Exception {
+
+ final HandlerMethod handler = new HandlerMethod(
+ controller,
+ controller.getClass().getMethod("handlePrivatelyCachedPageRequest"));
+
+ interceptor.setUseExpiresHeader(false);
+ interceptor.preHandle(request, response, handler);
+ assertFalse(response.containsHeader("Expires"));
+ }
}
Please sign in to comment.
Something went wrong with that request. Please try again.