Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#22 #24

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

#22 #24

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,9 @@
*/
int sharedMaxAge() default -1;

/**
* Sometimes caching need vary headers. E.g. 'Accept'.
*/
String[] vary() default {};

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,54 +14,59 @@
/**
* Provides a cache control handler interceptor to assign cache-control
* headers to HTTP responses.
*
*
* @author Scott Rossillo
*
*/
public class CacheControlHandlerInterceptor extends HandlerInterceptorAdapter implements HandlerInterceptor {

private static final String HEADER_EXPIRES = "Expires";
private static final String HEADER_CACHE_CONTROL = "Cache-Control";

private static final String HEADER_VARY = "Vary";

private boolean useExpiresHeader = true;

/**
* Creates a new cache control handler interceptor.
*/
public CacheControlHandlerInterceptor() {
super();
}

/**
* Assigns a <code>CacheControl</code> header to the given <code>response</code>.
*
*
* @param request the <code>HttpServletRequest</code>
* @param response the <code>HttpServletResponse</code>
* @param handler the handler for the given <code>request</code>
*/
protected final void assignCacheControlHeader(
final HttpServletRequest request,
final HttpServletResponse response,
final HttpServletResponse response,
final Object handler) {

final CacheControl cacheControl = this.getCacheControl(request, response, handler);
final String cacheControlHeader = this.createCacheControlHeader(cacheControl);

if (cacheControlHeader != null) {
response.setHeader(HEADER_CACHE_CONTROL, cacheControlHeader);
if (useExpiresHeader) {
response.setDateHeader(HEADER_EXPIRES, createExpiresHeader(cacheControl));
}
String[] vary = cacheControl.vary();
for (String v : vary) {
response.addHeader(HEADER_VARY, v);
}
}
}

/**
* Returns cache control header value from the given {@link CacheControl}
* annotation.
*
*
* @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 createCacheControlHeader(final CacheControl cacheControl) {
Expand Down Expand Up @@ -96,77 +101,77 @@ protected final String createCacheControlHeader(final CacheControl cacheControl)

return (builder.length() > 0 ? builder.toString() : null);
}

/**
* Returns an expires header value generated from the given
* 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) {

final 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 HttpServletResponse response,
final Object handler) {

if (handler == null || !(handler instanceof HandlerMethod)) {
return null;
}

final HandlerMethod handlerMethod = (HandlerMethod) handler;
CacheControl cacheControl = handlerMethod.getMethodAnnotation(CacheControl.class);

if (cacheControl == null) {
return handlerMethod.getBeanType().getAnnotation(CacheControl.class);
}

return cacheControl;
}

@Override
public final boolean preHandle(
final HttpServletRequest request,
final HttpServletResponse response,
final HttpServletResponse response,
final Object handler) throws Exception {

this.assignCacheControlHeader(request, response, handler);

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
*
* @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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ public String handlePubliclyCachedPageAndProxyRevalidatedRequest() {
public String handlePrivatelyCachedPageRequest() {
return null;
}

@CacheControl(policy = CachePolicy.PRIVATE, maxAge = 360, vary = "Accept")
public String handlePrivatelyCachedPageRequestWithVary() {
return null;
}

public String handleWithDefaultPolicy() {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,25 @@ public void testCacheControlPrivate() throws Exception {
assertTrue(response.getHeader("Cache-Control").contains("private"));
assertFalse(response.getHeader("Cache-Control").contains("public"));
}


@Test
public void testCacheControlPrivateWithVary() throws Exception {

final HandlerMethod handler = new HandlerMethod(
controller,
controller.getClass().getMethod("handlePrivatelyCachedPageRequestWithVary"));

interceptor.preHandle(request, response, handler);

System.err.println("Vary: " + response.getHeader("Vary"));

assertNotNull(response.getHeader("Cache-Control"));
assertTrue(response.getHeader("Cache-Control").contains("private"));
assertFalse(response.getHeader("Cache-Control").contains("public"));
assertTrue(response.getHeader("Vary").contains("Accept"));

}

@Test
public void testExpires() throws Exception {

Expand Down