From c66899bbead9dffe4381fe6a25428679ea72b3f0 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Sat, 1 Mar 2014 08:55:14 -0500 Subject: [PATCH] Use the server's date format. Slightly related to this AOSP bug report: https://code.google.com/p/android/issues/detail?id=66135 --- .../internal/http/HttpResponseCacheTest.java | 34 +++++++++++++++++++ .../okhttp/internal/http/CacheStrategy.java | 8 +++-- .../okhttp/internal/http/HttpDate.java | 20 +++++++---- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpResponseCacheTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpResponseCacheTest.java index 4cd8e7dc7..fc14d6e23 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpResponseCacheTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpResponseCacheTest.java @@ -1177,6 +1177,40 @@ public final class HttpResponseCacheTest { assertTrue(request.getHeaders().contains("If-Modified-Since: " + formatDate(since))); } + /** + * For Last-Modified and Date headers, we should echo the date back in the + * exact format we were served. + */ + @Test public void retainServedDateFormat() throws Exception { + // Serve a response with a non-standard date format that OkHttp supports. + Date lastModifiedDate = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(-1)); + Date servedDate = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(-2)); + DateFormat dateFormat = new SimpleDateFormat("EEE dd-MMM-yyyy HH:mm:ss z", Locale.US); + dateFormat.setTimeZone(TimeZone.getTimeZone("EDT")); + String lastModifiedString = dateFormat.format(lastModifiedDate); + String servedString = dateFormat.format(servedDate); + + // This response should be conditionally cached. + server.enqueue(new MockResponse() + .addHeader("Last-Modified: " + lastModifiedString) + .addHeader("Expires: " + servedString) + .setBody("A")); + server.enqueue(new MockResponse() + .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); + server.play(); + + assertEquals("A", readAscii(openConnection(server.getUrl("/")))); + assertEquals("A", readAscii(openConnection(server.getUrl("/")))); + + // The first request has no conditions. + RecordedRequest request1 = server.takeRequest(); + assertNull(request1.getHeader("If-Modified-Since")); + + // The 2nd request uses the server's date format. + RecordedRequest request2 = server.takeRequest(); + assertEquals(lastModifiedString, request2.getHeader("If-Modified-Since")); + } + @Test public void clientSuppliedConditionWithoutCachedResult() throws Exception { server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); server.play(); diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java index ae0acdfb7..7cc7e211d 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java @@ -97,9 +97,11 @@ public final class CacheStrategy { /** The server's time when the cached response was served, if known. */ private Date servedDate; + private String servedDateString; /** The last modified date of the cached response, if known. */ private Date lastModified; + private String lastModifiedString; /** * The expiration date of the cached response, if known. If both this field @@ -136,10 +138,12 @@ public final class CacheStrategy { String value = cacheResponse.headers().value(i); if ("Date".equalsIgnoreCase(fieldName)) { servedDate = HttpDate.parse(value); + servedDateString = value; } else if ("Expires".equalsIgnoreCase(fieldName)) { expires = HttpDate.parse(value); } else if ("Last-Modified".equalsIgnoreCase(fieldName)) { lastModified = HttpDate.parse(value); + lastModifiedString = value; } else if ("ETag".equalsIgnoreCase(fieldName)) { etag = value; } else if ("Age".equalsIgnoreCase(fieldName)) { @@ -232,9 +236,9 @@ public final class CacheStrategy { Request.Builder conditionalRequestBuilder = request.newBuilder(); if (lastModified != null) { - conditionalRequestBuilder.header("If-Modified-Since", HttpDate.format(lastModified)); + conditionalRequestBuilder.header("If-Modified-Since", lastModifiedString); } else if (servedDate != null) { - conditionalRequestBuilder.header("If-Modified-Since", HttpDate.format(servedDate)); + conditionalRequestBuilder.header("If-Modified-Since", servedDateString); } if (etag != null) { diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpDate.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpDate.java index bc8407e57..cdb697318 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpDate.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpDate.java @@ -45,13 +45,21 @@ public final class HttpDate { private static final String[] BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS = new String[] { "EEEE, dd-MMM-yy HH:mm:ss zzz", // RFC 1036 "EEE MMM d HH:mm:ss yyyy", // ANSI C asctime() - "EEE, dd-MMM-yyyy HH:mm:ss z", "EEE, dd-MMM-yyyy HH-mm-ss z", "EEE, dd MMM yy HH:mm:ss z", - "EEE dd-MMM-yyyy HH:mm:ss z", "EEE dd MMM yyyy HH:mm:ss z", "EEE dd-MMM-yyyy HH-mm-ss z", - "EEE dd-MMM-yy HH:mm:ss z", "EEE dd MMM yy HH:mm:ss z", "EEE,dd-MMM-yy HH:mm:ss z", - "EEE,dd-MMM-yyyy HH:mm:ss z", "EEE, dd-MM-yyyy HH:mm:ss z", + "EEE, dd-MMM-yyyy HH:mm:ss z", + "EEE, dd-MMM-yyyy HH-mm-ss z", + "EEE, dd MMM yy HH:mm:ss z", + "EEE dd-MMM-yyyy HH:mm:ss z", + "EEE dd MMM yyyy HH:mm:ss z", + "EEE dd-MMM-yyyy HH-mm-ss z", + "EEE dd-MMM-yy HH:mm:ss z", + "EEE dd MMM yy HH:mm:ss z", + "EEE,dd-MMM-yy HH:mm:ss z", + "EEE,dd-MMM-yyyy HH:mm:ss z", + "EEE, dd-MM-yyyy HH:mm:ss z", - /* RI bug 6641315 claims a cookie of this format was once served by www.yahoo.com */ - "EEE MMM d yyyy HH:mm:ss z", }; + /* RI bug 6641315 claims a cookie of this format was once served by www.yahoo.com */ + "EEE MMM d yyyy HH:mm:ss z", + }; private static final DateFormat[] BROWSER_COMPATIBLE_DATE_FORMATS = new DateFormat[BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.length];