Repository: square/okhttp
Issue: Caching broken by transparent gzip header mismatch

Following the technique described in the Cache javadoc (http://square.github.io/okhttp/javadoc/com/squareup/okhttp/Cache.html) we added the Cache-Control max-stale header to ensure we get a cached response when offline. We're doing this through Retrofit's RequestInterceptor, like so: 

```
requestFacade.addHeader("Cache-Control", "max-stale=" + maxStale);
```

This works great in okhttp 1.6: we get a response when offline. However, it no longer works in 2.0RC2 (or master). After some debugging, it turns out there _is_ a cache Response, but it's not returned after this test in Cache.get(Request):

```
if (!entry.matches(request, response)) 
```

which in turn is caused by OkHeaders.varyMatches(), which returns false for the Accept-Encoding field: cachedField [], actualField: [gzip].

This issue can be worked around by performing the gzip "by hand" by adding our own gzip header and decompressing the resulting response when necessary (this was not necessary in 1.6), as I described here, after an unrelated transparent gzip issue in an earlier version of okhttp: http://stackoverflow.com/questions/21585347/retrofit-okhttp-retrieve-gzipinputstream/22537697#22537697 


Changed files:
okhttp/src/main/java/com/squareup/okhttp/internal/http/OkHeaders.java, okhttp-tests/src/test/java/com/squareup/okhttp/CacheTest.java

diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/CacheTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/CacheTest.java
index 93163450b..b78a68e92 100644
--- a/okhttp-tests/src/test/java/com/squareup/okhttp/CacheTest.java
+++ b/okhttp-tests/src/test/java/com/squareup/okhttp/CacheTest.java
@@ -920,6 +920,19 @@ public final class CacheTest {
     assertEquals("DEFDEFDEF", readAscii(client.open(server.getUrl("/"))));
   }
 
+  /** https://github.com/square/okhttp/issues/947 */
+  @Test public void gzipAndVaryOnAcceptEncoding() throws Exception {
+    server.enqueue(new MockResponse()
+        .setBody(gzip("ABCABCABC"))
+        .addHeader("Content-Encoding: gzip")
+        .addHeader("Vary: Accept-Encoding")
+        .addHeader("Cache-Control: max-age=60"));
+    server.enqueue(new MockResponse().setBody("FAIL"));
+
+    assertEquals("ABCABCABC", readAscii(client.open(server.getUrl("/"))));
+    assertEquals("ABCABCABC", readAscii(client.open(server.getUrl("/"))));
+  }
+
   @Test public void conditionalCacheHitIsNotDoublePooled() throws Exception {
     server.enqueue(new MockResponse().addHeader("ETag: v1").setBody("A"));
     server.enqueue(new MockResponse()
diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/OkHeaders.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/OkHeaders.java
index 6736801fe..b09801b48 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/OkHeaders.java
+++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/OkHeaders.java
@@ -174,8 +174,12 @@ public final class OkHeaders {
     Set<String> varyFields = varyFields(response);
     if (varyFields.isEmpty()) return new Headers.Builder().build();
 
+    // Use the request headers sent over the network, since that's what the
+    // response varies on. Otherwise OkHttp-supplied headers like
+    // "Accept-Encoding: gzip" may be lost.
+    Headers requestHeaders = response.networkResponse().request().headers();
+
     Headers.Builder result = new Headers.Builder();
-    Headers requestHeaders = response.request().headers();
     for (int i = 0; i < requestHeaders.size(); i++) {
       String fieldName = requestHeaders.name(i);
       if (varyFields.contains(fieldName)) {