From b959bda46cfb3501adb9431e5df94fe6885437d7 Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Fri, 20 Apr 2012 10:49:18 +0200 Subject: [PATCH] Version 1.0.2: Header in 304-Antworten korrekt gesetzt --- cachecontrol/pom.xml | 2 +- .../cachecontrol/CacheControlInterceptor.java | 111 +++++++++++------- pom.xml | 4 +- 3 files changed, 71 insertions(+), 46 deletions(-) diff --git a/cachecontrol/pom.xml b/cachecontrol/pom.xml index 0db7fde2..85d42172 100644 --- a/cachecontrol/pom.xml +++ b/cachecontrol/pom.xml @@ -7,7 +7,7 @@ de.halbekunst juplo - 1.0.1 + 1.0.2 ${pom.parent.artifactId}-cachecontrol diff --git a/cachecontrol/src/main/java/de/halbekunst/juplo/cachecontrol/CacheControlInterceptor.java b/cachecontrol/src/main/java/de/halbekunst/juplo/cachecontrol/CacheControlInterceptor.java index a830e3c6..3d0c52d4 100644 --- a/cachecontrol/src/main/java/de/halbekunst/juplo/cachecontrol/CacheControlInterceptor.java +++ b/cachecontrol/src/main/java/de/halbekunst/juplo/cachecontrol/CacheControlInterceptor.java @@ -99,52 +99,36 @@ public class CacheControlInterceptor implements HandlerInterceptor { */ lastModified = lastModified - (lastModified % 1000); - String ifNoneMatch = request.getHeader(HEADER_IF_NONE_MATCH); - String eTag = cacheable.getETag(request); - /** - * 304-Antworten sollen nach dem {@plainlink - * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5 RFC - * 2616, Abschnitt 10.3.5} einen ETag-Header enthalten, wenn auch die - * 200-Antwort einen enthalten hätte. + * Cache-Control für HTTP/1.1-Clients generieren und setzen + * + * Nach {@plainlink http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-18#section-4.1 + * "HTTP/1.1, part 4: Conditional Requests", + * Abschnitt 4.1 "304 Not Modified" (Achtung: Entwurf -> work in progress!)} + * müssen die folgenden Felder in einer 304-Antwort + * enthalten sein, wenn sie auch in der ursprünglichen Antwort enthalten + * waren: + * */ - if (eTag != null) - response.setHeader(HEADER_ETAG, eTag); - - - if (ifModifiedSince >= lastModified && lastModified > 0) { - /** - * request.getDateHeader liefert die Zeit als long, oder -1, wenn der - * Header nicht existiert. D.h., wenn "If-Modified-Since" nicht gesetzt - * ist, wird die komplette Seite ausgeliefert. - * Der zusätzliche Test, ob lastModified größer 0 ist, ist nötig, um - * Fehler auszuschließen, wenn die Implementierung von Cachable - * negative Werte für Last-Modified zurückliefert. - */ - if (log.isDebugEnabled()) - log.debug("{}: Not modified since {}", url, new Date(ifModifiedSince)); - if (ifNoneMatch == null) { - /** Neue Anfrage oder HTTP/1.0 Client! */ - log.debug("{}: ETag nicht gesetzt -> 304", url); - response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); - return false; - } - } - - if (ifNoneMatch != null && ifNoneMatch.equals(eTag)) { - log.debug("{}: ETag {} not changed -> 304 ", url, ifNoneMatch); - response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); - return false; - } - - - log.debug("{}: first up!", url); - - /** HTTP/1.1-Caching-Header richtig setzen!! */ + /** + * Der Last-Modified-Header sollte (darf?) eventuell eigntlich nur für + * 200-Antworten gesetzt werden + * (s. http://webmasters.stackexchange.com/questions/25520/should-30) + * + * Da Squid sonst scheinbar nicht korrekt cached (und per if-not-modified + * aktualisiert) wird der Header aber trotzdem erst mal weiter erzeugt! + * (Ggf. noch mal prüfen, ob es eine Sinnestäuschung war, dass Squid + * Resourcen öfter als nötig komplett neu holt, wenn dieser Header fehlt!) + */ response.setDateHeader(HEADER_LAST_MODIFIED, lastModified); - /** Cache-Control für HTTP/1.1-Clients generieren */ Map cacheControl = new HashMap(cacheable.getCacheControl(request)); /** @@ -164,7 +148,7 @@ public class CacheControlInterceptor implements HandlerInterceptor { * Abschnitt 14.32}) */ response.setDateHeader(HEADER_EXPIRES, 0l); - response.addHeader(HEADER_PRAGMA, "no-cache"); + /** response.addHeader(HEADER_PRAGMA, "no-cache"); */ } else { /** * Hier muss nicht geprüft werden, ob cacheSeconds > 0 gilt, da in diesem @@ -190,6 +174,49 @@ public class CacheControlInterceptor implements HandlerInterceptor { response.addHeader(HEADER_CACHE_CONTROL, builder.toString()); } + + String ifNoneMatch = request.getHeader(HEADER_IF_NONE_MATCH); + String eTag = cacheable.getETag(request); + + /** + * 304-Antworten sollen nach dem {@plainlink + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5 RFC + * 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 (ifModifiedSince >= lastModified && lastModified > 0) { + /** + * request.getDateHeader liefert die Zeit als long, oder -1, wenn der + * Header nicht existiert. D.h., wenn "If-Modified-Since" nicht gesetzt + * ist, wird die komplette Seite ausgeliefert. + * Der zusätzliche Test, ob lastModified größer 0 ist, ist nötig, um + * Fehler auszuschließen, wenn die Implementierung von Cachable + * negative Werte für Last-Modified zurückliefert. + */ + if (log.isDebugEnabled()) + log.debug("{}: Not modified since {}", url, new Date(ifModifiedSince)); + + if (ifNoneMatch == null) { + /** Neue Anfrage oder HTTP/1.0 Client! */ + log.debug("{}: ETag nicht gesetzt -> 304", url); + response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); + return false; + } + } + + if (ifNoneMatch != null && ifNoneMatch.equals(eTag)) { + log.debug("{}: ETag {} not changed -> 304 ", url, ifNoneMatch); + response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); + return false; + } + + + log.debug("{}: first up!", url); + return true; } diff --git a/pom.xml b/pom.xml index abd2bf79..7357a3c7 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ de.halbekunst juplo - 1.0.1 + 1.0.2 Juplo pom http://www.halbekunst.de @@ -24,9 +24,7 @@ - test cachecontrol - utils -- 2.20.1