From 44e648e70606cc8d92f7db4268a468426b52da85 Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Mon, 14 Nov 2011 01:29:02 +0100 Subject: [PATCH] =?utf8?q?CacheControl=20ber=C3=BCcksichtigt=20die=20Regel?= =?utf8?q?n=20bzgl.=20starken=20vs.=20schwachen=20ETag's?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../juplo/cachecontrol/CacheControl.java | 55 ++++++++++++++++--- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/cachecontrol/src/main/java/de/halbekunst/juplo/cachecontrol/CacheControl.java b/cachecontrol/src/main/java/de/halbekunst/juplo/cachecontrol/CacheControl.java index 0d79436e..77e2004c 100644 --- a/cachecontrol/src/main/java/de/halbekunst/juplo/cachecontrol/CacheControl.java +++ b/cachecontrol/src/main/java/de/halbekunst/juplo/cachecontrol/CacheControl.java @@ -31,6 +31,7 @@ public class CacheControl { public static final String HEADER_PRAGMA = "Pragma"; public static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since"; public static final String HEADER_IF_NONE_MATCH = "If-None-Match"; + public static final String HEADER_RANGE = "Range"; private static final ThreadLocal tl = new ThreadLocal(); @@ -162,8 +163,15 @@ public class CacheControl { * 2616, Abschnitt 10.3.5} einen ETag-Header enthalten, wenn auch die * 200-Antwort einen enthalten hätte. */ - if (eTag != null) - response.setHeader(HEADER_ETAG, eTag); + if (eTag != null) { + StringBuilder builder = new StringBuilder(); + if (controller.isETagWeak()) + builder.append("W/"); + builder.append('"'); + builder.append(eTag); + builder.append('"'); + response.setHeader(HEADER_ETAG, builder.toString()); + } if (ifModifiedSince >= lastModified && lastModified > 0) { @@ -186,10 +194,31 @@ public class CacheControl { } } - if (ifNoneMatch != null && ifNoneMatch.equals(eTag)) { - log.debug("{}: ETag {} not changed -> 304 ", url, ifNoneMatch); - response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); - return false; + if (ifNoneMatch != null) { + boolean weak = false; + if (ifNoneMatch.startsWith("W/")) { + weak = true; + ifNoneMatch = ifNoneMatch.substring(3, ifNoneMatch.length() - 1); + } + else { + ifNoneMatch = ifNoneMatch.substring(1, ifNoneMatch.length() - 1); + } + + if (!weak || (request.getMethod().equals("GET") && request.getHeader(HEADER_RANGE) == null)) { + /** + * Die Gleichheit gilt nur, wenn die ETag's der Anfrage _und_ der + * Antwort stark sind (starke Gleichheit!), oder wenn die Antwort nur + * schwache Gleichheit fordert... + */ + if (ifNoneMatch.equals(eTag) && (controller.isETagWeak() || !weak)) { + log.debug("{}: ETag {} not changed -> 304 ", url, ifNoneMatch); + response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); + return false; + } + } + else { + log.warn("{}: ignoring weak ETag W/\"{}\", because the request was no GET-request or the Range-Header was present!", url, ifNoneMatch); + } } @@ -273,6 +302,7 @@ public class CacheControl { int getCacheSeconds(HttpServletRequest request) throws Exception; long getLastModified(HttpServletRequest request) throws Exception; String getETag(HttpServletRequest request) throws Exception; + boolean isETagWeak(); void cacheControl(HttpServletRequest request, Map cacheControlMap) throws Exception; } @@ -294,6 +324,7 @@ public class CacheControl { private boolean isLastModifiedMethodDefined; private boolean isETagMethodDefined; private boolean isCacheControlMethodDefined; + private boolean weak; ReflectionCacheMethodHandle(Object handler) throws NoSuchMethodException { @@ -302,7 +333,7 @@ public class CacheControl { cacheSeconds = CacheControl.this.defaultCacheSeconds; lastModified = CacheControl.this.defaultLastModified; - eTag = null; + eTag = ""; /** Class-Level-Annotations auslesen */ for (Annotation annotation : handler.getClass().getAnnotations()) { @@ -325,7 +356,9 @@ public class CacheControl { continue; } if (annotation.annotationType().equals(ETag.class)) { - eTag = ((ETag)annotation).value(); + ETag eTagAnnotation = (ETag)annotation; + eTag = eTagAnnotation.value(); + weak = eTagAnnotation.weak(); isETagMethodDefined = true; continue; } @@ -359,6 +392,7 @@ public class CacheControl { if (isETagMethodDefined) throw new IllegalArgumentException("Die Annotation @ETag wurde in der Klasse " + handler.getClass().getSimpleName() + " mehrfach verwendet!"); eTagMethod = method; + weak = ((ETag)annotation).weak(); isETagMethodDefined = true; continue; } @@ -427,6 +461,11 @@ public class CacheControl { return (String)eTagMethod.invoke(handler, request); } + @Override + public boolean isETagWeak() { + return weak; + } + @Override public void cacheControl( HttpServletRequest request, -- 2.20.1