1e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/* 2e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Copyright (C) 2011 The Android Open Source Project 3e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 4e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License"); 5e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * you may not use this file except in compliance with the License. 6e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * You may obtain a copy of the License at 7e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 8e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * http://www.apache.org/licenses/LICENSE-2.0 9e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 10e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Unless required by applicable law or agreed to in writing, software 11e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS, 12e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * See the License for the specific language governing permissions and 14e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * limitations under the License. 15e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 16e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 17e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpackage com.squareup.okhttp; 18e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 19e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.internal.Internal; 20e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.internal.SslContextBuilder; 21e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.internal.Util; 2271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fullerimport com.squareup.okhttp.internal.io.InMemoryFileSystem; 23e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.mockwebserver.MockResponse; 24e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.mockwebserver.MockWebServer; 25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.mockwebserver.RecordedRequest; 26e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.File; 27e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.IOException; 28e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.CookieHandler; 29e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.CookieManager; 30e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.HttpCookie; 31e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.HttpURLConnection; 32e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.ResponseCache; 33e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.security.Principal; 34e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.security.cert.Certificate; 35e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.text.DateFormat; 36e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.text.SimpleDateFormat; 37e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.ArrayList; 38e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.Arrays; 39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.Date; 40e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.Iterator; 41e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.List; 42e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.Locale; 43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.NoSuchElementException; 44e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.TimeZone; 45e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.concurrent.TimeUnit; 46e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.concurrent.atomic.AtomicReference; 473be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport javax.net.ssl.HostnameVerifier; 483be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport javax.net.ssl.SSLContext; 493be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport javax.net.ssl.SSLSession; 503be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport okio.Buffer; 513be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport okio.BufferedSink; 523be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport okio.BufferedSource; 533be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport okio.GzipSink; 543be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport okio.Okio; 553be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport org.junit.After; 563be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport org.junit.Before; 573be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport org.junit.Rule; 583be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fullerimport org.junit.Test; 59e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 60e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static com.squareup.okhttp.mockwebserver.SocketPolicy.DISCONNECT_AT_END; 61e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertEquals; 62e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertFalse; 63e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertNotNull; 64e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertNull; 65e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertTrue; 66e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.fail; 67e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 68e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/** Test caching with {@link OkUrlFactory}. */ 69e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpublic final class CacheTest { 70e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private static final HostnameVerifier NULL_HOSTNAME_VERIFIER = new HostnameVerifier() { 71e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public boolean verify(String s, SSLSession sslSession) { 72e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return true; 73e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 74e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller }; 75e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 7671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Rule public MockWebServer server = new MockWebServer(); 7771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Rule public MockWebServer server2 = new MockWebServer(); 786c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer @Rule public InMemoryFileSystem fileSystem = new InMemoryFileSystem(); 79e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 8071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller private final SSLContext sslContext = SslContextBuilder.localhost(); 81e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private final OkHttpClient client = new OkHttpClient(); 82e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private Cache cache; 83e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private final CookieManager cookieManager = new CookieManager(); 84e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 85e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Before public void setUp() throws Exception { 86e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.setProtocolNegotiationEnabled(false); 8771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller cache = new Cache(new File("/cache/"), Integer.MAX_VALUE, fileSystem); 88e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setCache(cache); 89e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller CookieHandler.setDefault(cookieManager); 90e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 91e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 92e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @After public void tearDown() throws Exception { 93e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller ResponseCache.setDefault(null); 94e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller CookieHandler.setDefault(null); 956c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer cache.delete(); 96e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 97e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 98e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 99e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Test that response caching is consistent with the RI and the spec. 100e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 101e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 102e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void responseCachingByResponseCode() throws Exception { 103e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Test each documented HTTP/1.1 code, plus the first unused value in each range. 104e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // We can't test 100 because it's not really a response. 107e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // assertCached(false, 100); 108e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 101); 109e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 102); 110e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 200); 111e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 201); 112e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 202); 113e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 203); 114e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 204); 115e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 205); 116e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 206); //Electing to not cache partial responses 117e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 207); 118e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 300); 119e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 301); 120e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 302); 121e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 303); 122e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 304); 123e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 305); 124e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 306); 125e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 307); 126e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 308); 127e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 400); 128e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 401); 129e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 402); 130e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 403); 131e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 404); 132e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 405); 133e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 406); 134e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 408); 135e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 409); 136e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // the HTTP spec permits caching 410s, but the RI doesn't. 137e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 410); 138e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 411); 139e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 412); 140e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 413); 141e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 414); 142e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 415); 143e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 416); 144e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 417); 145e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 418); 146e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 147e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 500); 148e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(true, 501); 149e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 502); 150e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 503); 151e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 504); 152e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 505); 153e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCached(false, 506); 154e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 155e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 156e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void assertCached(boolean shouldPut, int responseCode) throws Exception { 157e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server = new MockWebServer(); 158e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockResponse mockResponse = new MockResponse() 159e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 160e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 161e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(responseCode) 162e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("ABCDE") 163e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("WWW-Authenticate: challenge"); 164e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller if (responseCode == HttpURLConnection.HTTP_PROXY_AUTH) { 165e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller mockResponse.addHeader("Proxy-Authenticate: Basic realm=\"protected area\""); 166e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) { 167e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller mockResponse.addHeader("WWW-Authenticate: Basic realm=\"protected area\""); 16871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } else if (responseCode == HttpURLConnection.HTTP_NO_CONTENT 16971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller || responseCode == HttpURLConnection.HTTP_RESET) { 17071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller mockResponse.setBody(""); // We forbid bodies for 204 and 205. 171e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 172e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(mockResponse); 173e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.start(); 174e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 175e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 17671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 177e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 178e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 179e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(responseCode, response.code()); 180e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 181e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Exhaust the content stream. 182e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response.body().string(); 183e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 184e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response cached = cache.get(request); 185e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller if (shouldPut) { 186e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotNull(Integer.toString(responseCode), cached); 187e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller cached.body().close(); 188e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } else { 189e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(Integer.toString(responseCode), cached); 190e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 191e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers 192e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 193e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 194e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void responseCachingAndInputStreamSkipWithFixedLength() throws IOException { 195e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testResponseCaching(TransferKind.FIXED_LENGTH); 196e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 197e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 198e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void responseCachingAndInputStreamSkipWithChunkedEncoding() throws IOException { 199e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testResponseCaching(TransferKind.CHUNKED); 200e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 201e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 202e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void responseCachingAndInputStreamSkipWithNoLengthHeaders() throws IOException { 203e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testResponseCaching(TransferKind.END_OF_STREAM); 204e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 205e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 206e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 207e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Skipping bytes in the input stream caused ResponseCache corruption. 208e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * http://code.google.com/p/android/issues/detail?id=8175 209e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 210e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void testResponseCaching(TransferKind transferKind) throws IOException { 211e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockResponse mockResponse = new MockResponse() 212e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 213e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 214e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setStatus("HTTP/1.1 200 Fantastic"); 215e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller transferKind.setBody(mockResponse, "I love puppies but hate spiders", 1); 216e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(mockResponse); 217e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 218e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Make sure that calling skip() doesn't omit bytes from the cache. 21971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Request request = new Request.Builder().url(server.url("/")).build(); 220e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request).execute(); 221e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 222e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller BufferedSource in1 = response1.body().source(); 223e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("I love ", in1.readUtf8("I love ".length())); 224e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller in1.skip("puppies but hate ".length()); 225e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("spiders", in1.readUtf8("spiders".length())); 226e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(in1.exhausted()); 227e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller in1.close(); 228e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getWriteSuccessCount()); 229e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getWriteAbortCount()); 230e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 231e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request).execute(); 232e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller BufferedSource in2 = response2.body().source(); 233e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("I love puppies but hate spiders", 234e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller in2.readUtf8("I love puppies but hate spiders".length())); 235e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(200, response2.code()); 236e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Fantastic", response2.message()); 237e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 238e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(in2.exhausted()); 239e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller in2.close(); 240e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getWriteSuccessCount()); 241e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getWriteAbortCount()); 242e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getRequestCount()); 243e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getHitCount()); 244e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 245e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 246e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void secureResponseCaching() throws IOException { 247e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 248e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 249e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 250e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 251e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("ABC")); 252e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 253e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setSslSocketFactory(sslContext.getSocketFactory()); 254e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER); 255e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 25671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Request request = new Request.Builder().url(server.url("/")).build(); 257e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request).execute(); 258e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller BufferedSource in = response1.body().source(); 259e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABC", in.readUtf8()); 260e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 261e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // OpenJDK 6 fails on this line, complaining that the connection isn't open yet 262e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String suite = response1.handshake().cipherSuite(); 263e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller List<Certificate> localCerts = response1.handshake().localCertificates(); 264e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller List<Certificate> serverCerts = response1.handshake().peerCertificates(); 265e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Principal peerPrincipal = response1.handshake().peerPrincipal(); 266e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Principal localPrincipal = response1.handshake().localPrincipal(); 267e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 268e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request).execute(); // Cached! 2696c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertEquals("ABC", response2.body().string()); 270e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 271e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getRequestCount()); 272e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getNetworkCount()); 273e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getHitCount()); 274e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 275e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(suite, response2.handshake().cipherSuite()); 276e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(localCerts, response2.handshake().localCertificates()); 277e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(serverCerts, response2.handshake().peerCertificates()); 278e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(peerPrincipal, response2.handshake().peerPrincipal()); 279e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(localPrincipal, response2.handshake().localPrincipal()); 280e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 281e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 282e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void responseCachingAndRedirects() throws Exception { 283e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 284e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 285e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 286e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 287e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Location: /foo")); 288e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 289e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 290e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 291e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("ABC")); 292e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 293e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("DEF")); 294e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 29571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Request request = new Request.Builder().url(server.url("/")).build(); 296e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request).execute(); 297e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABC", response1.body().string()); 298e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 299e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request).execute(); // Cached! 300e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABC", response2.body().string()); 301e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 302e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(4, cache.getRequestCount()); // 2 requests + 2 redirects 303e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getNetworkCount()); 304e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getHitCount()); 305e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 306e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 307e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void redirectToCachedResult() throws Exception { 308e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 309e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 310e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("ABC")); 311e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 312e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 313e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Location: /foo")); 314e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 315e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("DEF")); 316e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 31771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Request request1 = new Request.Builder().url(server.url("/foo")).build(); 318e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request1).execute(); 319e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABC", response1.body().string()); 320e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest recordedRequest1 = server.takeRequest(); 321e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("GET /foo HTTP/1.1", recordedRequest1.getRequestLine()); 322e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, recordedRequest1.getSequenceNumber()); 323e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 32471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Request request2 = new Request.Builder().url(server.url("/bar")).build(); 325e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request2).execute(); 326e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABC", response2.body().string()); 327e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest recordedRequest2 = server.takeRequest(); 328e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("GET /bar HTTP/1.1", recordedRequest2.getRequestLine()); 329e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, recordedRequest2.getSequenceNumber()); 330e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 331e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // an unrelated request should reuse the pooled connection 33271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Request request3 = new Request.Builder().url(server.url("/baz")).build(); 333e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response3 = client.newCall(request3).execute(); 334e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("DEF", response3.body().string()); 335e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest recordedRequest3 = server.takeRequest(); 336e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("GET /baz HTTP/1.1", recordedRequest3.getRequestLine()); 337e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, recordedRequest3.getSequenceNumber()); 338e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 339e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 340e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void secureResponseCachingAndRedirects() throws IOException { 341e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 342e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 343e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 344e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 345e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 346e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Location: /foo")); 347e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 348e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 349e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 350e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("ABC")); 351e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 352e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("DEF")); 353e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 354e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setSslSocketFactory(sslContext.getSocketFactory()); 355e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER); 356e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 35771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response1 = get(server.url("/")); 358e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABC", response1.body().string()); 359e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotNull(response1.handshake().cipherSuite()); 360e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 361e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Cached! 36271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response2 = get(server.url("/")); 363e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABC", response2.body().string()); 364e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotNull(response2.handshake().cipherSuite()); 365e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 366e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4 367e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getHitCount()); 368e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(response1.handshake().cipherSuite(), response2.handshake().cipherSuite()); 369e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 370e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 371e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 372e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * We've had bugs where caching and cross-protocol redirects yield class 373e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * cast exceptions internal to the cache because we incorrectly assumed that 374e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * HttpsURLConnection was always HTTPS and HttpURLConnection was always HTTP; 375e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * in practice redirects mean that each can do either. 376e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 377e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * https://github.com/square/okhttp/issues/214 378e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 379e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void secureResponseCachingAndProtocolRedirects() throws IOException { 380e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server2.useHttps(sslContext.getSocketFactory(), false); 381e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server2.enqueue(new MockResponse() 382e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 383e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 384e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("ABC")); 385e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server2.enqueue(new MockResponse() 386e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("DEF")); 387e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 388e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 389e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 390e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 391e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 39271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .addHeader("Location: " + server2.url("/"))); 393e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 394e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setSslSocketFactory(sslContext.getSocketFactory()); 395e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER); 396e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 39771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response1 = get(server.url("/")); 398e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABC", response1.body().string()); 399e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 400e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Cached! 40171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response2 = get(server.url("/")); 402e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABC", response2.body().string()); 403e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 404e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4 405e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getHitCount()); 406e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 407e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 408e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void foundCachedWithExpiresHeader() throws Exception { 409e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller temporaryRedirectCachedWithCachingHeader(302, "Expires", formatDate(1, TimeUnit.HOURS)); 410e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 411e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 412e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void foundCachedWithCacheControlHeader() throws Exception { 413e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller temporaryRedirectCachedWithCachingHeader(302, "Cache-Control", "max-age=60"); 414e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 415e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 416e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void temporaryRedirectCachedWithExpiresHeader() throws Exception { 417e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller temporaryRedirectCachedWithCachingHeader(307, "Expires", formatDate(1, TimeUnit.HOURS)); 418e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 419e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 420e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void temporaryRedirectCachedWithCacheControlHeader() throws Exception { 421e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller temporaryRedirectCachedWithCachingHeader(307, "Cache-Control", "max-age=60"); 422e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 423e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 424e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void foundNotCachedWithoutCacheHeader() throws Exception { 425e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller temporaryRedirectNotCachedWithoutCachingHeader(302); 426e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 427e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 428e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void temporaryRedirectNotCachedWithoutCacheHeader() throws Exception { 429e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller temporaryRedirectNotCachedWithoutCachingHeader(307); 430e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 431e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 432e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void temporaryRedirectCachedWithCachingHeader( 433e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller int responseCode, String headerName, String headerValue) throws Exception { 434e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 435e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(responseCode) 436e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader(headerName, headerValue) 437e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Location", "/a")); 438e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 439e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader(headerName, headerValue) 440e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("a")); 441e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 442e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("b")); 443e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 444e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("c")); 445e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 44671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 447e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("a", get(url).body().string()); 448e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("a", get(url).body().string()); 449e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 450e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 451e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void temporaryRedirectNotCachedWithoutCachingHeader(int responseCode) throws Exception { 452e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 453e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(responseCode) 454e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Location", "/a")); 455e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 456e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("a")); 457e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 458e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("b")); 459e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 46071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 461e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("a", get(url).body().string()); 462e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("b", get(url).body().string()); 463e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 464e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 4656c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer /** https://github.com/square/okhttp/issues/2198 */ 4666c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer @Test public void cachedRedirect() throws IOException { 4676c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer server.enqueue(new MockResponse() 4686c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer .setResponseCode(301) 4696c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer .addHeader("Cache-Control: max-age=60") 4706c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer .addHeader("Location: /bar")); 4716c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer server.enqueue(new MockResponse() 4726c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer .setBody("ABC")); 4736c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer server.enqueue(new MockResponse() 4746c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer .setBody("ABC")); 4756c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 4766c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Request request1 = new Request.Builder().url(server.url("/")).build(); 4776c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Response response1 = client.newCall(request1).execute(); 4786c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertEquals("ABC", response1.body().string()); 4796c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 4806c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Request request2 = new Request.Builder().url(server.url("/")).build(); 4816c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Response response2 = client.newCall(request2).execute(); 4826c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertEquals("ABC", response2.body().string()); 4836c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 4846c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 485e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void serverDisconnectsPrematurelyWithContentLengthHeader() throws IOException { 486e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testServerPrematureDisconnect(TransferKind.FIXED_LENGTH); 487e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 488e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 489e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void serverDisconnectsPrematurelyWithChunkedEncoding() throws IOException { 490e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testServerPrematureDisconnect(TransferKind.CHUNKED); 491e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 492e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 493e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void serverDisconnectsPrematurelyWithNoLengthHeaders() throws IOException { 494e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Intentionally empty. This case doesn't make sense because there's no 495e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // such thing as a premature disconnect when the disconnect itself 496e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // indicates the end of the data stream. 497e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 498e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 499e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException { 500e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockResponse mockResponse = new MockResponse(); 501e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller transferKind.setBody(mockResponse, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 16); 502e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(truncateViolently(mockResponse, 16)); 503e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 504e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("Request #2")); 505e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 50671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller BufferedSource bodySource = get(server.url("/")).body().source(); 507e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABCDE", bodySource.readUtf8Line()); 508e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller try { 509e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller bodySource.readUtf8Line(); 510e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller fail("This implementation silently ignored a truncated HTTP body."); 511e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } catch (IOException expected) { 512e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } finally { 513e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller bodySource.close(); 514e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 515e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 516e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getWriteAbortCount()); 517e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getWriteSuccessCount()); 51871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response = get(server.url("/")); 519e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Request #2", response.body().string()); 520e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getWriteAbortCount()); 521e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getWriteSuccessCount()); 522e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 523e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 524e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void clientPrematureDisconnectWithContentLengthHeader() throws IOException { 525e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testClientPrematureDisconnect(TransferKind.FIXED_LENGTH); 526e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 527e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 528e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void clientPrematureDisconnectWithChunkedEncoding() throws IOException { 529e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testClientPrematureDisconnect(TransferKind.CHUNKED); 530e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 531e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 532e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void clientPrematureDisconnectWithNoLengthHeaders() throws IOException { 533e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testClientPrematureDisconnect(TransferKind.END_OF_STREAM); 534e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 535e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 536e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException { 537e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Setting a low transfer speed ensures that stream discarding will time out. 538e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockResponse mockResponse = new MockResponse() 539e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .throttleBody(6, 1, TimeUnit.SECONDS); 540e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller transferKind.setBody(mockResponse, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 1024); 541e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(mockResponse); 542e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 543e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("Request #2")); 544e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 54571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response1 = get(server.url("/")); 546e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller BufferedSource in = response1.body().source(); 547e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABCDE", in.readUtf8(5)); 548e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller in.close(); 549e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller try { 550e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller in.readByte(); 551e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller fail("Expected an IllegalStateException because the source is closed."); 552e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } catch (IllegalStateException expected) { 553e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 554e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 555e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getWriteAbortCount()); 556e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getWriteSuccessCount()); 55771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response2 = get(server.url("/")); 558e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Request #2", response2.body().string()); 559e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getWriteAbortCount()); 560e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getWriteSuccessCount()); 561e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 562e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 563e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void defaultExpirationDateFullyCachedForLessThan24Hours() throws Exception { 564e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // last modified: 105 seconds ago 565e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // served: 5 seconds ago 566e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // default lifetime: (105 - 5) / 10 = 10 seconds 567e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // expires: 10 seconds from served date = 5 seconds from now 568e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 569e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS)) 570e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS)) 571e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 572e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 57371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 574e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = get(url); 575e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 576e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 577e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = get(url); 578e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 579e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(response2.header("Warning")); 580e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 581e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 582e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void defaultExpirationDateConditionallyCached() throws Exception { 583e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // last modified: 115 seconds ago 584e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // served: 15 seconds ago 585e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // default lifetime: (115 - 15) / 10 = 10 seconds 586e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // expires: 10 seconds from served date = 5 seconds ago 587e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String lastModifiedDate = formatDate(-115, TimeUnit.SECONDS); 588e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 589e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + lastModifiedDate) 590e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-15, TimeUnit.SECONDS))); 591e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(lastModifiedDate, conditionalRequest.getHeader("If-Modified-Since")); 592e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 593e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 594e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void defaultExpirationDateFullyCachedForMoreThan24Hours() throws Exception { 595e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // last modified: 105 days ago 596e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // served: 5 days ago 597e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // default lifetime: (105 - 5) / 10 = 10 days 598e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // expires: 10 days from served date = 5 days from now 599e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 600e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.DAYS)) 601e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-5, TimeUnit.DAYS)) 602e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 603e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 60471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 60571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response = get(server.url("/")); 606e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response.body().string()); 607e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("113 HttpURLConnection \"Heuristic expiration\"", response.header("Warning")); 608e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 609e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 610e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void noDefaultExpirationForUrlsWithQueryString() throws Exception { 611e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 612e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS)) 613e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS)) 614e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 615e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 616e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 617e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 61871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/").newBuilder().addQueryParameter("foo", "bar").build(); 619e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 620e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", get(url).body().string()); 621e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 622e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 623e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void expirationDateInThePastWithLastModifiedHeader() throws Exception { 624e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 625e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 626e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + lastModifiedDate) 627e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 628e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(lastModifiedDate, conditionalRequest.getHeader("If-Modified-Since")); 629e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 630e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 631e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void expirationDateInThePastWithNoLastModifiedHeader() throws Exception { 632e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotCached(new MockResponse() 633e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 634e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 635e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 636e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void expirationDateInTheFuture() throws Exception { 637e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertFullyCached(new MockResponse() 638e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 639e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 640e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 641e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void maxAgePreferredWithMaxAgeAndExpires() throws Exception { 642e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertFullyCached(new MockResponse() 643e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.HOURS)) 644e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)) 645e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60")); 646e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 647e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 648e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void maxAgeInThePastWithDateAndLastModifiedHeaders() throws Exception { 649e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 650e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 651e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS)) 652e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + lastModifiedDate) 653e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60")); 654e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(lastModifiedDate, conditionalRequest.getHeader("If-Modified-Since")); 655e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 656e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 657e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void maxAgeInThePastWithDateHeaderButNoLastModifiedHeader() throws Exception { 658e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Chrome interprets max-age relative to the local clock. Both our cache 659e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // and Firefox both use the earlier of the local and server's clock. 660e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotCached(new MockResponse() 661e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS)) 662e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60")); 663e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 664e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 665e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void maxAgeInTheFutureWithDateHeader() throws Exception { 666e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertFullyCached(new MockResponse() 667e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.HOURS)) 668e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60")); 669e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 670e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 671e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void maxAgeInTheFutureWithNoDateHeader() throws Exception { 672e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertFullyCached(new MockResponse() 673e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60")); 674e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 675e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 676e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void maxAgeWithLastModifiedButNoServedDate() throws Exception { 677e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertFullyCached(new MockResponse() 678e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 679e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60")); 680e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 681e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 682e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void maxAgeInTheFutureWithDateAndLastModifiedHeaders() throws Exception { 683e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertFullyCached(new MockResponse() 684e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 685e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 686e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60")); 687e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 688e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 689e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void maxAgePreferredOverLowerSharedMaxAge() throws Exception { 690e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertFullyCached(new MockResponse() 691e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 692e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: s-maxage=60") 693e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=180")); 694e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 695e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 696e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void maxAgePreferredOverHigherMaxAge() throws Exception { 697e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotCached(new MockResponse() 698e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 699e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: s-maxage=180") 700e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60")); 701e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 702e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 703e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMethodOptionsIsNotCached() throws Exception { 704e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRequestMethod("OPTIONS", false); 705e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 706e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 707e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMethodGetIsCached() throws Exception { 708e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRequestMethod("GET", true); 709e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 710e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 711e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMethodHeadIsNotCached() throws Exception { 712e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // We could support this but choose not to for implementation simplicity 713e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRequestMethod("HEAD", false); 714e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 715e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 716e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMethodPostIsNotCached() throws Exception { 717e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // We could support this but choose not to for implementation simplicity 718e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRequestMethod("POST", false); 719e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 720e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 721e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMethodPutIsNotCached() throws Exception { 722e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRequestMethod("PUT", false); 723e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 724e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 725e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMethodDeleteIsNotCached() throws Exception { 726e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRequestMethod("DELETE", false); 727e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 728e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 729e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMethodTraceIsNotCached() throws Exception { 730e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRequestMethod("TRACE", false); 731e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 732e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 733e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void testRequestMethod(String requestMethod, boolean expectCached) throws Exception { 734e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // 1. seed the cache (potentially) 735e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // 2. expect a cache hit or miss 736e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 737e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 738e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("X-Response-ID: 1")); 739e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 740e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("X-Response-ID: 2")); 741e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 74271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 743e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 744e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 745e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 746e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .method(requestMethod, requestBodyOrNull(requestMethod)) 747e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 748e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request).execute(); 749e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response1.body().close(); 750e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("1", response1.header("X-Response-ID")); 751e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 752e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = get(url); 753e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response2.body().close(); 754e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller if (expectCached) { 755e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("1", response2.header("X-Response-ID")); 756e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } else { 757e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("2", response2.header("X-Response-ID")); 758e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 759e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 760e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 761e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private RequestBody requestBodyOrNull(String requestMethod) { 762e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return (requestMethod.equals("POST") || requestMethod.equals("PUT")) 763e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller ? RequestBody.create(MediaType.parse("text/plain"), "foo") 764e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller : null; 765e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 766e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 767e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void postInvalidatesCache() throws Exception { 768e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testMethodInvalidates("POST"); 769e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 770e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 771e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void putInvalidatesCache() throws Exception { 772e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testMethodInvalidates("PUT"); 773e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 774e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 775e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void deleteMethodInvalidatesCache() throws Exception { 776e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testMethodInvalidates("DELETE"); 777e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 778e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 779e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void testMethodInvalidates(String requestMethod) throws Exception { 780e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // 1. seed the cache 781e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // 2. invalidate it 782e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // 3. expect a cache miss 783e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 784e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 785e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 786e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 787e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 788e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 789e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("C")); 790e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 79171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 792e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 793e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 794e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 795e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 796e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 797e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .method(requestMethod, requestBodyOrNull(requestMethod)) 798e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 799e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response invalidate = client.newCall(request).execute(); 800e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", invalidate.body().string()); 801e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 802e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("C", get(url).body().string()); 803e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 804e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 805e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void postInvalidatesCacheWithUncacheableResponse() throws Exception { 806e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // 1. seed the cache 807e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // 2. invalidate it with uncacheable response 808e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // 3. expect a cache miss 809e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 810e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 811e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 812e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 813e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B") 814e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(500)); 815e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 816e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("C")); 817e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 81871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 819e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 820e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 821e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 822e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 823e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 824e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .method("POST", requestBodyOrNull("POST")) 825e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 826e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response invalidate = client.newCall(request).execute(); 827e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", invalidate.body().string()); 828e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 829e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("C", get(url).body().string()); 830e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 831e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 832e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void etag() throws Exception { 833e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 834e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("ETag: v1")); 835e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("v1", conditionalRequest.getHeader("If-None-Match")); 836e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 837e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 8383be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fuller /** If both If-Modified-Since and If-None-Match conditions apply, send only If-None-Match. */ 839e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void etagAndExpirationDateInThePast() throws Exception { 840e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 841e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 842e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("ETag: v1") 843e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + lastModifiedDate) 844e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 845e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("v1", conditionalRequest.getHeader("If-None-Match")); 8463be78b8b0ca13d9e05e2327acb8d8654f719a3f6Neil Fuller assertNull(conditionalRequest.getHeader("If-Modified-Since")); 847e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 848e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 849e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void etagAndExpirationDateInTheFuture() throws Exception { 850e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertFullyCached(new MockResponse() 851e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("ETag: v1") 852e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 853e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 854e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 855e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 856e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void cacheControlNoCache() throws Exception { 857e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotCached(new MockResponse() 858e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: no-cache")); 859e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 860e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 861e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void cacheControlNoCacheAndExpirationDateInTheFuture() throws Exception { 862e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 863e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 864e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + lastModifiedDate) 865e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 866e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: no-cache")); 867e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(lastModifiedDate, conditionalRequest.getHeader("If-Modified-Since")); 868e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 869e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 870e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void pragmaNoCache() throws Exception { 871e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotCached(new MockResponse() 872e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Pragma: no-cache")); 873e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 874e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 875e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void pragmaNoCacheAndExpirationDateInTheFuture() throws Exception { 876e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 877e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 878e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + lastModifiedDate) 879e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 880e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Pragma: no-cache")); 881e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(lastModifiedDate, conditionalRequest.getHeader("If-Modified-Since")); 882e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 883e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 884e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void cacheControlNoStore() throws Exception { 885e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotCached(new MockResponse() 886e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: no-store")); 887e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 888e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 889e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void cacheControlNoStoreAndExpirationDateInTheFuture() throws Exception { 890e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotCached(new MockResponse() 891e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 892e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 893e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: no-store")); 894e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 895e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 896e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void partialRangeResponsesDoNotCorruptCache() throws Exception { 897e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // 1. request a range 898e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // 2. request a full document, expecting a cache miss 899e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 900e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("AA") 901e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_PARTIAL) 902e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 903e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Content-Range: bytes 1000-1001/2000")); 904e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 905e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("BB")); 906e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 90771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 908e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 909e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 910e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 911e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Range", "bytes=1000-1001") 912e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 913e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response range = client.newCall(request).execute(); 914e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("AA", range.body().string()); 915e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 916e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("BB", get(url).body().string()); 917e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 918e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 919e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void serverReturnsDocumentOlderThanCache() throws Exception { 920e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 921e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 922e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 923e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 924e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 925e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B") 926e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-4, TimeUnit.HOURS))); 927e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 92871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 929e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 930e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 931e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 932e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 933e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 934e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void clientSideNoStore() throws Exception { 935e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 936e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 937e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 938e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 939e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 940e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 941e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 942e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request1 = new Request.Builder() 94371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 944e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .cacheControl(new CacheControl.Builder().noStore().build()) 945e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 946e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request1).execute(); 947e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 948e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 949e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request2 = new Request.Builder() 95071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 951e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 952e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request2).execute(); 953e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", response2.body().string()); 954e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 955e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 956e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void nonIdentityEncodingAndConditionalCache() throws Exception { 957e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNonIdentityEncodingCached(new MockResponse() 958e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 959e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 960e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 961e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 962e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void nonIdentityEncodingAndFullCache() throws Exception { 963e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNonIdentityEncodingCached(new MockResponse() 964e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 965e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 966e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 967e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 968e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void assertNonIdentityEncodingCached(MockResponse response) throws Exception { 969e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(response 970e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody(gzip("ABCABCABC")) 971e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Content-Encoding: gzip")); 972e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 973e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 974e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 975e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 976e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 977e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // At least three request/response pairs are required because after the first request is cached 978e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // a different execution path might be taken. Thus modifications to the cache applied during 979e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // the second request might not be visible until another request is performed. 98071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("ABCABCABC", get(server.url("/")).body().string()); 98171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("ABCABCABC", get(server.url("/")).body().string()); 98271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("ABCABCABC", get(server.url("/")).body().string()); 983e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 984e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 985e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void notModifiedSpecifiesEncoding() throws Exception { 986e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 987e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody(gzip("ABCABCABC")) 988e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Content-Encoding: gzip") 989e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 990e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 991e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 992e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED) 993e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Content-Encoding: gzip")); 994e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 995e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("DEFDEFDEF")); 996e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 99771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("ABCABCABC", get(server.url("/")).body().string()); 99871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("ABCABCABC", get(server.url("/")).body().string()); 99971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("DEFDEFDEF", get(server.url("/")).body().string()); 1000e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1001e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1002e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** https://github.com/square/okhttp/issues/947 */ 1003e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void gzipAndVaryOnAcceptEncoding() throws Exception { 1004e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1005e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody(gzip("ABCABCABC")) 1006e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Content-Encoding: gzip") 1007e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Accept-Encoding") 1008e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60")); 1009e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1010e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("FAIL")); 1011e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 101271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("ABCABCABC", get(server.url("/")).body().string()); 101371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("ABCABCABC", get(server.url("/")).body().string()); 1014e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1015e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1016e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void conditionalCacheHitIsNotDoublePooled() throws Exception { 1017e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1018e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("ETag: v1") 1019e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1020e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1021e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .clearHeaders() 1022e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1023e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1024e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller ConnectionPool pool = ConnectionPool.getDefault(); 1025e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller pool.evictAll(); 1026e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setConnectionPool(pool); 1027e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 102871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 102971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 10306c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertEquals(1, client.getConnectionPool().getIdleConnectionCount()); 1031e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1032e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1033e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void expiresDateBeforeModifiedDate() throws Exception { 1034e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertConditionallyCached(new MockResponse() 1035e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1036e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(-2, TimeUnit.HOURS))); 1037e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1038e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1039e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMaxAge() throws IOException { 1040e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1041e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 1042e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 1043e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES)) 1044e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 1045e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1046e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1047e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 104871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1049e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1050e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 105171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 1052e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Cache-Control", "max-age=30") 1053e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1054e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1055e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", response.body().string()); 1056e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1057e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1058e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMinFresh() throws IOException { 1059e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1060e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 1061e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1062e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 1063e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1064e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1065e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 106671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1067e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1068e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 106971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 1070e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Cache-Control", "min-fresh=120") 1071e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1072e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1073e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", response.body().string()); 1074e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1075e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1076e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMaxStale() throws IOException { 1077e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1078e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 1079e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=120") 1080e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES))); 1081e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1082e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1083e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 108471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1085e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1086e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 108771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 1088e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Cache-Control", "max-stale=180") 1089e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1090e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1091e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response.body().string()); 1092e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("110 HttpURLConnection \"Response is stale\"", response.header("Warning")); 1093e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1094e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1095e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMaxStaleDirectiveWithNoValue() throws IOException { 1096e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Add a stale response to the cache. 1097e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1098e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 1099e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=120") 1100e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES))); 1101e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1102e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1103e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 110471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // With max-stale, we'll return that stale response. 1107e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 110871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 1109e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Cache-Control", "max-stale") 1110e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1111e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1112e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response.body().string()); 1113e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("110 HttpURLConnection \"Response is stale\"", response.header("Warning")); 1114e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1115e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1116e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestMaxStaleNotHonoredWithMustRevalidate() throws IOException { 1117e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1118e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 1119e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=120, must-revalidate") 1120e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES))); 1121e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1122e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1123e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 112471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1125e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1126e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 112771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 1128e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Cache-Control", "max-stale=180") 1129e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1130e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1131e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", response.body().string()); 1132e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1133e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1134e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestOnlyIfCachedWithNoResponseCached() throws IOException { 1135e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // (no responses enqueued) 1136e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1137e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 113871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 1139e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Cache-Control", "only-if-cached") 1140e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1141e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1142e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(response.body().source().exhausted()); 1143e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(504, response.code()); 1144e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getRequestCount()); 1145e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getNetworkCount()); 1146e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getHitCount()); 1147e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1148e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1149e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestOnlyIfCachedWithFullResponseCached() throws IOException { 1150e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1151e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 1152e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=30") 1153e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 1154e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 115571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1156e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 115771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 1158e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Cache-Control", "only-if-cached") 1159e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1160e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1161e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response.body().string()); 1162e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getRequestCount()); 1163e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getNetworkCount()); 1164e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getHitCount()); 1165e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1166e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1167e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestOnlyIfCachedWithConditionalResponseCached() throws IOException { 1168e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1169e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 1170e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=30") 1171e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES))); 1172e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 117371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1174e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 117571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 1176e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Cache-Control", "only-if-cached") 1177e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1178e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1179e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(response.body().source().exhausted()); 1180e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(504, response.code()); 1181e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getRequestCount()); 1182e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getNetworkCount()); 1183e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getHitCount()); 1184e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1185e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1186e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException { 1187e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1188e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1189e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 119071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1191e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 119271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 1193e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Cache-Control", "only-if-cached") 1194e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1195e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1196e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(response.body().source().exhausted()); 1197e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(504, response.code()); 1198e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getRequestCount()); 1199e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getNetworkCount()); 1200e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getHitCount()); 1201e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1202e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1203e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestCacheControlNoCache() throws Exception { 1204e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1205e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 1206e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 1207e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1208e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1209e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1210e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1211e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 121271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1213e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 1214e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 1215e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1216e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Cache-Control", "no-cache") 1217e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1218e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1219e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", response.body().string()); 1220e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1221e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1222e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void requestPragmaNoCache() throws Exception { 1223e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1224e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 1225e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 1226e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1227e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1228e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1229e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1230e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 123171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1232e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 1233e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 1234e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1235e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Pragma", "no-cache") 1236e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1237e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1238e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", response.body().string()); 1239e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1240e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1241e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void clientSuppliedIfModifiedSinceWithCachedResult() throws Exception { 1242e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockResponse response = new MockResponse() 1243e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("ETag: v3") 1244e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0"); 1245e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String ifModifiedSinceDate = formatDate(-24, TimeUnit.HOURS); 1246e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest request = 1247e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertClientSuppliedCondition(response, "If-Modified-Since", ifModifiedSinceDate); 1248e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(ifModifiedSinceDate, request.getHeader("If-Modified-Since")); 1249e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request.getHeader("If-None-Match")); 1250e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1251e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1252e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void clientSuppliedIfNoneMatchSinceWithCachedResult() throws Exception { 1253e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String lastModifiedDate = formatDate(-3, TimeUnit.MINUTES); 1254e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockResponse response = new MockResponse() 1255e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + lastModifiedDate) 1256e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 1257e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0"); 1258e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest request = assertClientSuppliedCondition(response, "If-None-Match", "v1"); 1259e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("v1", request.getHeader("If-None-Match")); 1260e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request.getHeader("If-Modified-Since")); 1261e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1262e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1263e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private RecordedRequest assertClientSuppliedCondition(MockResponse seed, String conditionName, 1264e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String conditionValue) throws Exception { 1265e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(seed.setBody("A")); 1266e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1267e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1268e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 126971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1270e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 1271e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1272e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 1273e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1274e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header(conditionName, conditionValue) 1275e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1276e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1277e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, response.code()); 1278e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("", response.body().string()); 1279e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1280e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.takeRequest(); // seed 1281e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return server.takeRequest(); 1282e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1283e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1284e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 1285e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * For Last-Modified and Date headers, we should echo the date back in the 1286e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * exact format we were served. 1287e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 1288e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void retainServedDateFormat() throws Exception { 1289e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Serve a response with a non-standard date format that OkHttp supports. 1290e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Date lastModifiedDate = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(-1)); 1291e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Date servedDate = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(-2)); 1292e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller DateFormat dateFormat = new SimpleDateFormat("EEE dd-MMM-yyyy HH:mm:ss z", Locale.US); 1293e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller dateFormat.setTimeZone(TimeZone.getTimeZone("EDT")); 1294e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String lastModifiedString = dateFormat.format(lastModifiedDate); 1295e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String servedString = dateFormat.format(servedDate); 1296e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1297e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // This response should be conditionally cached. 1298e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1299e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + lastModifiedString) 1300e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + servedString) 1301e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1302e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1303e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1304e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 130571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 130671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1307e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1308e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // The first request has no conditions. 1309e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest request1 = server.takeRequest(); 1310e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request1.getHeader("If-Modified-Since")); 1311e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1312e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // The 2nd request uses the server's date format. 1313e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest request2 = server.takeRequest(); 1314e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(lastModifiedString, request2.getHeader("If-Modified-Since")); 1315e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1316e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1317e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void clientSuppliedConditionWithoutCachedResult() throws Exception { 1318e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1319e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1320e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1321e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 132271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")) 1323e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("If-Modified-Since", formatDate(-24, TimeUnit.HOURS)) 1324e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1325e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1326e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, response.code()); 1327e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("", response.body().string()); 1328e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1329e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1330e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void authorizationRequestFullyCached() throws Exception { 1331e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1332e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1333e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1334e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1335e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1336e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 133771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1338e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 1339e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1340e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Authorization", "password") 1341e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1342e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1343e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response.body().string()); 1344e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 1345e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1346e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1347e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void contentLocationDoesNotPopulateCache() throws Exception { 1348e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1349e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1350e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Content-Location: /bar") 1351e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1352e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1353e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1354e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 135571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/foo")).body().string()); 135671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("B", get(server.url("/bar")).body().string()); 1357e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1358e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1359e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void connectionIsReturnedToPoolAfterConditionalSuccess() throws Exception { 1360e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1361e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1362e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 1363e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1364e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1365e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1366e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1367e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1368e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 136971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/a")).body().string()); 137071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/a")).body().string()); 137171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("B", get(server.url("/b")).body().string()); 1372e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1373e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, server.takeRequest().getSequenceNumber()); 1374e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, server.takeRequest().getSequenceNumber()); 1375e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, server.takeRequest().getSequenceNumber()); 1376e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1377e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1378e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void statisticsConditionalCacheMiss() throws Exception { 1379e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1380e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1381e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 1382e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1383e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1384e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1385e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1386e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("C")); 1387e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 138871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1389e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getRequestCount()); 1390e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getNetworkCount()); 1391e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getHitCount()); 139271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("B", get(server.url("/")).body().string()); 139371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("C", get(server.url("/")).body().string()); 1394e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(3, cache.getRequestCount()); 1395e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(3, cache.getNetworkCount()); 1396e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getHitCount()); 1397e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1398e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1399e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void statisticsConditionalCacheHit() throws Exception { 1400e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1401e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1402e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 1403e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1404e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1405e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1406e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1407e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1408e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 140971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1410e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getRequestCount()); 1411e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getNetworkCount()); 1412e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getHitCount()); 141371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 141471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1415e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(3, cache.getRequestCount()); 1416e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(3, cache.getNetworkCount()); 1417e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getHitCount()); 1418e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1419e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1420e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void statisticsFullCacheHit() throws Exception { 1421e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1422e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1423e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1424e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 142571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1426e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getRequestCount()); 1427e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getNetworkCount()); 1428e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, cache.getHitCount()); 142971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 143071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1431e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(3, cache.getRequestCount()); 1432e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, cache.getNetworkCount()); 1433e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, cache.getHitCount()); 1434e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1435e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1436e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyMatchesChangedRequestHeaderField() throws Exception { 1437e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1438e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1439e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Accept-Language") 1440e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1441e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1442e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1443e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 144471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1445e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request frRequest = new Request.Builder() 1446e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1447e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "fr-CA") 1448e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1449e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response frResponse = client.newCall(frRequest).execute(); 1450e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", frResponse.body().string()); 1451e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1452e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request enRequest = new Request.Builder() 1453e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1454e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "en-US") 1455e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1456e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response enResponse = client.newCall(enRequest).execute(); 1457e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", enResponse.body().string()); 1458e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1459e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1460e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyMatchesUnchangedRequestHeaderField() throws Exception { 1461e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1462e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1463e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Accept-Language") 1464e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1465e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1466e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1467e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 146871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1469e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 1470e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1471e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "fr-CA") 1472e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1473e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request).execute(); 1474e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1475e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request1 = new Request.Builder() 1476e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1477e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "fr-CA") 1478e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1479e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request1).execute(); 1480e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 1481e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1482e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1483e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyMatchesAbsentRequestHeaderField() throws Exception { 1484e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1485e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1486e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Foo") 1487e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1488e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1489e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1490e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 149171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 149271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1493e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1494e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1495e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyMatchesAddedRequestHeaderField() throws Exception { 1496e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1497e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1498e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Foo") 1499e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1500e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1501e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1502e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 150371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1504e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 150571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")).header("Foo", "bar") 1506e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1507e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1508e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", response.body().string()); 1509e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1510e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1511e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyMatchesRemovedRequestHeaderField() throws Exception { 1512e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1513e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1514e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Foo") 1515e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1516e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1517e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1518e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1519e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 152071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")).header("Foo", "bar") 1521e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1522e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response fooresponse = client.newCall(request).execute(); 1523e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", fooresponse.body().string()); 152471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("B", get(server.url("/")).body().string()); 1525e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1526e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1527e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyFieldsAreCaseInsensitive() throws Exception { 1528e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1529e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1530e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: ACCEPT-LANGUAGE") 1531e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1532e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1533e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1534e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 153571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1536e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 1537e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1538e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "fr-CA") 1539e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1540e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request).execute(); 1541e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1542e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request1 = new Request.Builder() 1543e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1544e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("accept-language", "fr-CA") 1545e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1546e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request1).execute(); 1547e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 1548e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1549e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1550e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyMultipleFieldsWithMatch() throws Exception { 1551e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1552e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1553e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Accept-Language, Accept-Charset") 1554e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Accept-Encoding") 1555e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1556e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1557e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1558e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 155971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1560e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 1561e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1562e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "fr-CA") 1563e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Charset", "UTF-8") 1564e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Encoding", "identity") 1565e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1566e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request).execute(); 1567e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1568e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request1 = new Request.Builder() 1569e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1570e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "fr-CA") 1571e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Charset", "UTF-8") 1572e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Encoding", "identity") 1573e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1574e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request1).execute(); 1575e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 1576e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1577e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1578e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyMultipleFieldsWithNoMatch() throws Exception { 1579e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1580e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1581e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Accept-Language, Accept-Charset") 1582e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Accept-Encoding") 1583e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1584e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1585e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1586e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 158771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1588e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request frRequest = new Request.Builder() 1589e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1590e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "fr-CA") 1591e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Charset", "UTF-8") 1592e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Encoding", "identity") 1593e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1594e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response frResponse = client.newCall(frRequest).execute(); 1595e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", frResponse.body().string()); 1596e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request enRequest = new Request.Builder() 1597e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1598e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "en-CA") 1599e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Charset", "UTF-8") 1600e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Encoding", "identity") 1601e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1602e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response enResponse = client.newCall(enRequest).execute(); 1603e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", enResponse.body().string()); 1604e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1605e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1606e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyMultipleFieldValuesWithMatch() throws Exception { 1607e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1608e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1609e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Accept-Language") 1610e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1611e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1612e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1613e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 161471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1615e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request1 = new Request.Builder() 1616e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1617e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Accept-Language", "fr-CA, fr-FR") 1618e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Accept-Language", "en-US") 1619e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1620e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request1).execute(); 1621e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1622e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1623e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request2 = new Request.Builder() 1624e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1625e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Accept-Language", "fr-CA, fr-FR") 1626e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Accept-Language", "en-US") 1627e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1628e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request2).execute(); 1629e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 1630e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1631e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1632e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyMultipleFieldValuesWithNoMatch() throws Exception { 1633e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1634e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1635e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Accept-Language") 1636e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1637e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1638e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1639e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 164071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1641e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request1 = new Request.Builder() 1642e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1643e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Accept-Language", "fr-CA, fr-FR") 1644e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Accept-Language", "en-US") 1645e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1646e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request1).execute(); 1647e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1648e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1649e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request2 = new Request.Builder() 1650e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1651e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Accept-Language", "fr-CA") 1652e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Accept-Language", "en-US") 1653e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1654e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request2).execute(); 1655e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", response2.body().string()); 1656e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1657e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1658e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyAsterisk() throws Exception { 165971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(new MockResponse() 1660e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1661e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: *") 1662e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1663e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1664e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1665e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 166671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 166771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("B", get(server.url("/")).body().string()); 1668e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1669e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1670e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void varyAndHttps() throws Exception { 1671e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 1672e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1673e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1674e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Vary: Accept-Language") 1675e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1676e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1677e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1678e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1679e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setSslSocketFactory(sslContext.getSocketFactory()); 1680e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER); 1681e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 168271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1683e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request1 = new Request.Builder() 1684e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1685e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "en-US") 1686e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1687e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = client.newCall(request1).execute(); 1688e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1689e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1690e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request2 = new Request.Builder() 1691e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 1692e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .header("Accept-Language", "en-US") 1693e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1694e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = client.newCall(request2).execute(); 1695e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 1696e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1697e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1698e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void cachePlusCookies() throws Exception { 1699e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1700e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Set-Cookie: a=FIRST; domain=" + server.getCookieDomain() + ";") 1701e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1702e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 1703e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1704e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1705e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Set-Cookie: a=SECOND; domain=" + server.getCookieDomain() + ";") 1706e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1707e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 170871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1709e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 1710e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCookies(url, "a=FIRST"); 1711e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 1712e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertCookies(url, "a=SECOND"); 1713e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1714e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1715e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void getHeadersReturnsNetworkEndToEndHeaders() throws Exception { 1716e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1717e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Allow: GET, HEAD") 1718e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1719e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 1720e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1721e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1722e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Allow: GET, HEAD, PUT") 1723e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1724e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 172571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response1 = get(server.url("/")); 1726e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1727e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("GET, HEAD", response1.header("Allow")); 1728e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 172971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response2 = get(server.url("/")); 1730e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 1731e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("GET, HEAD, PUT", response2.header("Allow")); 1732e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1733e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1734e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void getHeadersReturnsCachedHopByHopHeaders() throws Exception { 1735e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1736e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Transfer-Encoding: identity") 1737e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1738e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 1739e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1740e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1741e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Transfer-Encoding: none") 1742e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1743e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 174471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response1 = get(server.url("/")); 1745e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1746e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("identity", response1.header("Transfer-Encoding")); 1747e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 174871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response2 = get(server.url("/")); 1749e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 1750e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("identity", response2.header("Transfer-Encoding")); 1751e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1752e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1753e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void getHeadersDeletesCached100LevelWarnings() throws Exception { 1754e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1755e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Warning: 199 test danger") 1756e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1757e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 1758e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1759e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1760e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1761e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 176271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response1 = get(server.url("/")); 1763e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1764e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("199 test danger", response1.header("Warning")); 1765e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 176671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response2 = get(server.url("/")); 1767e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 1768e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(null, response2.header("Warning")); 1769e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1770e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1771e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void getHeadersRetainsCached200LevelWarnings() throws Exception { 1772e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1773e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Warning: 299 test danger") 1774e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1775e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 1776e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1777e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1778e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1779e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 178071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response1 = get(server.url("/")); 1781e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1782e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("299 test danger", response1.header("Warning")); 1783e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 178471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response2 = get(server.url("/")); 1785e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 1786e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("299 test danger", response2.header("Warning")); 1787e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1788e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 178971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller public void assertCookies(HttpUrl url, String... expectedCookies) throws Exception { 1790e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller List<String> actualCookies = new ArrayList<>(); 179171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller for (HttpCookie cookie : cookieManager.getCookieStore().get(url.uri())) { 1792e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller actualCookies.add(cookie.toString()); 1793e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1794e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(Arrays.asList(expectedCookies), actualCookies); 1795e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1796e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1797e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void doNotCachePartialResponse() throws Exception { 1798e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNotCached(new MockResponse() 179971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .setResponseCode(HttpURLConnection.HTTP_PARTIAL) 180071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.HOURS)) 180171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .addHeader("Content-Range: bytes 100-100/200") 180271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .addHeader("Cache-Control: max-age=60")); 1803e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1804e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1805e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void conditionalHitUpdatesCache() throws Exception { 1806e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1807e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(0, TimeUnit.SECONDS)) 1808e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 1809e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1810e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1811e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=30") 1812e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Allow: GET, HEAD") 1813e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1814e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1815e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1816e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1817e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // cache miss; seed the cache 181871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response1 = get(server.url("/a")); 1819e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 1820e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(null, response1.header("Allow")); 1821e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1822e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // conditional cache hit; update the cache 182371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response2 = get(server.url("/a")); 1824e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(HttpURLConnection.HTTP_OK, response2.code()); 1825e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 1826e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("GET, HEAD", response2.header("Allow")); 1827e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1828e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // full cache hit 182971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response3 = get(server.url("/a")); 1830e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response3.body().string()); 1831e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("GET, HEAD", response3.header("Allow")); 1832e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1833e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(2, server.getRequestCount()); 1834e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1835e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1836e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void responseSourceHeaderCached() throws IOException { 1837e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1838e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 1839e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=30") 1840e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 1841e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 184271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 1843e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 184471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .url(server.url("/")).header("Cache-Control", "only-if-cached") 1845e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 1846e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = client.newCall(request).execute(); 1847e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response.body().string()); 1848e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1849e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1850e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void responseSourceHeaderConditionalCacheFetched() throws IOException { 1851e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1852e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 1853e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=30") 1854e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(-31, TimeUnit.MINUTES))); 1855e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1856e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B") 1857e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=30") 1858e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 1859e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 186071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 186171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response = get(server.url("/")); 1862e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", response.body().string()); 1863e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1864e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1865e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void responseSourceHeaderConditionalCacheNotFetched() throws IOException { 1866e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1867e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A") 1868e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 1869e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 1870e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1871e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(304)); 1872e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 187371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(server.url("/")).body().string()); 187471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response = get(server.url("/")); 1875e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response.body().string()); 1876e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1877e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1878e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void responseSourceHeaderFetched() throws IOException { 1879e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1880e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1881e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 188271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response = get(server.url("/")); 1883e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response.body().string()); 1884e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1885e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1886e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void emptyResponseHeaderNameFromCacheIsLenient() throws Exception { 1887e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Headers.Builder headers = new Headers.Builder() 1888e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .add("Cache-Control: max-age=120"); 1889e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Internal.instance.addLenient(headers, ": A"); 1890e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1891e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setHeaders(headers.build()) 1892e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("body")); 1893e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 189471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Response response = get(server.url("/")); 1895e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response.header("")); 18966c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertEquals("body", response.body().string()); 1897e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1898e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1899e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 1900e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Old implementations of OkHttp's response cache wrote header fields like 1901e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * ":status: 200 OK". This broke our cached response parser because it split 1902e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * on the first colon. This regression test exists to help us read these old 1903e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * bad cache entries. 1904e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 1905e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * https://github.com/square/okhttp/issues/227 1906e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 1907e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void testGoldenCacheResponse() throws Exception { 1908e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller cache.close(); 1909e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1910e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .clearHeaders() 1911e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1912e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 191371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1914e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String urlKey = Util.md5Hex(url.toString()); 1915e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String entryMetadata = "" 1916e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "" + url + "\n" 1917e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "GET\n" 1918e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "0\n" 1919e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "HTTP/1.1 200 OK\n" 1920e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "7\n" 1921e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + ":status: 200 OK\n" 1922e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + ":version: HTTP/1.1\n" 1923e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "etag: foo\n" 1924e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "content-length: 3\n" 1925e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "OkHttp-Received-Millis: " + System.currentTimeMillis() + "\n" 1926e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "X-Android-Response-Source: NETWORK 200\n" 1927e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "OkHttp-Sent-Millis: " + System.currentTimeMillis() + "\n" 1928e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "\n" 1929e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\n" 1930e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "1\n" 1931e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "MIIBpDCCAQ2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDEw1qd2lsc29uLmxvY2FsMB4XDTEzMDgy" 1932e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "OTA1MDE1OVoXDTEzMDgzMDA1MDE1OVowGDEWMBQGA1UEAxMNandpbHNvbi5sb2NhbDCBnzANBgkqhkiG9w0BAQEF" 1933e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "AAOBjQAwgYkCgYEAlFW+rGo/YikCcRghOyKkJanmVmJSce/p2/jH1QvNIFKizZdh8AKNwojt3ywRWaDULA/RlCUc" 1934e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "ltF3HGNsCyjQI/+Lf40x7JpxXF8oim1E6EtDoYtGWAseelawus3IQ13nmo6nWzfyCA55KhAWf4VipelEy8DjcuFK" 1935e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "v6L0xwXnI0ECAwEAATANBgkqhkiG9w0BAQsFAAOBgQAuluNyPo1HksU3+Mr/PyRQIQS4BI7pRXN8mcejXmqyscdP" 1936e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "7S6J21FBFeRR8/XNjVOp4HT9uSc2hrRtTEHEZCmpyoxixbnM706ikTmC7SN/GgM+SmcoJ1ipJcNcl8N0X6zym4dm" 1937e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "yFfXKHu2PkTo7QFdpOJFvP3lIigcSZXozfmEDg==\n" 1938e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "-1\n"; 1939e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String entryBody = "abc"; 1940e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String journalBody = "" 1941e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "libcore.io.DiskLruCache\n" 1942e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "1\n" 1943e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "201105\n" 1944e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "2\n" 1945e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "\n" 1946e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller + "CLEAN " + urlKey + " " + entryMetadata.length() + " " + entryBody.length() + "\n"; 1947e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller writeFile(cache.getDirectory(), urlKey + ".0", entryMetadata); 1948e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller writeFile(cache.getDirectory(), urlKey + ".1", entryBody); 1949e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller writeFile(cache.getDirectory(), "journal", journalBody); 195071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller cache = new Cache(cache.getDirectory(), Integer.MAX_VALUE, fileSystem); 1951e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setCache(cache); 1952e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1953e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = get(url); 1954e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(entryBody, response.body().string()); 1955e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("3", response.header("Content-Length")); 1956e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("foo", response.header("etag")); 1957e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1958e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1959e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void evictAll() throws Exception { 1960e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1961e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 1962e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1963e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1964e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 1965e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 196671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1967e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 1968e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.getCache().evictAll(); 1969e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, client.getCache().getSize()); 1970e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", get(url).body().string()); 1971e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1972e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1973e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void networkInterceptorInvokedForConditionalGet() throws Exception { 1974e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1975e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("ETag: v1") 1976e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 1977e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1978e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1979e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1980e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Seed the cache. 198171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 1982e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 1983e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1984e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller final AtomicReference<String> ifNoneMatch = new AtomicReference<>(); 1985e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.networkInterceptors().add(new Interceptor() { 1986e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public Response intercept(Chain chain) throws IOException { 1987e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller ifNoneMatch.compareAndSet(null, chain.request().header("If-None-Match")); 1988e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return chain.proceed(chain.request()); 1989e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1990e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller }); 1991e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1992e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Confirm the value is cached and intercepted. 1993e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 1994e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("v1", ifNoneMatch.get()); 1995e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1996e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1997e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void networkInterceptorNotInvokedForFullyCached() throws Exception { 1998e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1999e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 2000e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 2001e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2002e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Seed the cache. 200371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 2004e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 2005e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2006e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Confirm the interceptor isn't exercised. 2007e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.networkInterceptors().add(new Interceptor() { 2008e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public Response intercept(Chain chain) throws IOException { 2009e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller throw new AssertionError(); 2010e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2011e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller }); 2012e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 2013e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2014e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2015e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void iterateCache() throws Exception { 2016e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Put some responses in the cache. 2017e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2018e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("a")); 201971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl urlA = server.url("/a"); 2020e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("a", get(urlA).body().string()); 2021e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2022e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2023e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("b")); 202471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl urlB = server.url("/b"); 2025e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("b", get(urlB).body().string()); 2026e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2027e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2028e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("c")); 202971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl urlC = server.url("/c"); 2030e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("c", get(urlC).body().string()); 2031e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2032e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Confirm the iterator returns those responses... 2033e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Iterator<String> i = cache.urls(); 2034e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(i.hasNext()); 2035e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(urlA.toString(), i.next()); 2036e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(i.hasNext()); 2037e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(urlB.toString(), i.next()); 2038e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(i.hasNext()); 2039e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(urlC.toString(), i.next()); 2040e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2041e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // ... and nothing else. 2042e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertFalse(i.hasNext()); 2043e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller try { 2044e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller i.next(); 2045e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller fail(); 2046e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } catch (NoSuchElementException expected) { 2047e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2048e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2049e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2050e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void iteratorRemoveFromCache() throws Exception { 2051e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Put a response in the cache. 2052e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2053e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=60") 2054e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("a")); 205571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/a"); 2056e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("a", get(url).body().string()); 2057e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2058e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Remove it with iteration. 2059e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Iterator<String> i = cache.urls(); 2060e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(url.toString(), i.next()); 2061e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller i.remove(); 2062e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2063e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Confirm that subsequent requests suffer a cache miss. 2064e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2065e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("b")); 2066e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("b", get(url).body().string()); 2067e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2068e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2069e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void iteratorRemoveWithoutNextThrows() throws Exception { 2070e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Put a response in the cache. 2071e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2072e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("a")); 207371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/a"); 2074e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("a", get(url).body().string()); 2075e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2076e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Iterator<String> i = cache.urls(); 2077e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(i.hasNext()); 2078e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller try { 2079e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller i.remove(); 2080e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller fail(); 2081e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } catch (IllegalStateException expected) { 2082e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2083e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2084e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2085e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void iteratorRemoveOncePerCallToNext() throws Exception { 2086e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Put a response in the cache. 2087e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2088e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("a")); 208971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/a"); 2090e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("a", get(url).body().string()); 2091e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2092e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Iterator<String> i = cache.urls(); 2093e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(url.toString(), i.next()); 2094e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller i.remove(); 2095e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2096e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Too many calls to remove(). 2097e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller try { 2098e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller i.remove(); 2099e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller fail(); 2100e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } catch (IllegalStateException expected) { 2101e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2102e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2103e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2104e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void elementEvictedBetweenHasNextAndNext() throws Exception { 2105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Put a response in the cache. 2106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2107e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("a")); 210871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/a"); 2109e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("a", get(url).body().string()); 2110e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2111e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // The URL will remain available if hasNext() returned true... 2112e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Iterator<String> i = cache.urls(); 2113e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(i.hasNext()); 2114e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2115e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // ...so even when we evict the element, we still get something back. 2116e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller cache.evictAll(); 2117e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(url.toString(), i.next()); 2118e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2119e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Remove does nothing. But most importantly, it doesn't throw! 2120e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller i.remove(); 2121e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2122e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2123e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void elementEvictedBeforeHasNextIsOmitted() throws Exception { 2124e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Put a response in the cache. 2125e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2126e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("a")); 212771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/a"); 2128e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("a", get(url).body().string()); 2129e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2130e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Iterator<String> i = cache.urls(); 2131e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller cache.evictAll(); 2132e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2133e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // The URL was evicted before hasNext() made any promises. 2134e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertFalse(i.hasNext()); 2135e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller try { 2136e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller i.next(); 2137e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller fail(); 2138e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } catch (NoSuchElementException expected) { 2139e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2140e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2141e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 214271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller /** Test https://github.com/square/okhttp/issues/1712. */ 214371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void conditionalMissUpdatesCache() throws Exception { 214471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(new MockResponse() 214571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .addHeader("ETag: v1") 214671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .setBody("A")); 214771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(new MockResponse() 214871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 214971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(new MockResponse() 215071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .addHeader("ETag: v2") 215171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .setBody("B")); 215271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(new MockResponse() 215371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 215471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 215571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 215671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(url).body().string()); 215771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("A", get(url).body().string()); 215871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("B", get(url).body().string()); 215971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("B", get(url).body().string()); 216071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 216171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals(null, server.takeRequest().getHeader("If-None-Match")); 216271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("v1", server.takeRequest().getHeader("If-None-Match")); 216371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("v1", server.takeRequest().getHeader("If-None-Match")); 216471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("v2", server.takeRequest().getHeader("If-None-Match")); 216571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 216671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 216771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller private Response get(HttpUrl url) throws IOException { 2168e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Request request = new Request.Builder() 2169e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .url(url) 2170e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .build(); 2171e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return client.newCall(request).execute(); 2172e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2173e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2174e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2175e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void writeFile(File directory, String file, String content) throws IOException { 217671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller BufferedSink sink = Okio.buffer(fileSystem.sink(new File(directory, file))); 2177e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller sink.writeUtf8(content); 2178e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller sink.close(); 2179e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2180e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2181e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 2182e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * @param delta the offset from the current date to use. Negative 2183e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * values yield dates in the past; positive values yield dates in the 2184e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * future. 2185e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 2186e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private String formatDate(long delta, TimeUnit timeUnit) { 2187e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta))); 2188e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2189e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2190e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private String formatDate(Date date) { 2191e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); 2192e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller rfc1123.setTimeZone(TimeZone.getTimeZone("GMT")); 2193e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return rfc1123.format(date); 2194e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2195e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2196e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void assertNotCached(MockResponse response) throws Exception { 2197e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(response.setBody("A")); 2198e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2199e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 2200e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 220171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 2202e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 2203e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", get(url).body().string()); 2204e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2205e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2206e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** @return the request with the conditional get headers. */ 2207e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private RecordedRequest assertConditionallyCached(MockResponse response) throws Exception { 2208e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // scenario 1: condition succeeds 2209e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(response.setBody("A").setStatus("HTTP/1.1 200 A-OK")); 2210e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2211e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 2212e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2213e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // scenario 2: condition fails 2214e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(response.setBody("B") 2215e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setStatus("HTTP/1.1 200 B-OK")); 2216e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2217e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setStatus("HTTP/1.1 200 C-OK") 2218e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("C")); 2219e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 222071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl valid = server.url("/valid"); 2221e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response1 = get(valid); 2222e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response1.body().string()); 2223e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(HttpURLConnection.HTTP_OK, response1.code()); 2224e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A-OK", response1.message()); 2225e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response2 = get(valid); 2226e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", response2.body().string()); 2227e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(HttpURLConnection.HTTP_OK, response2.code()); 2228e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A-OK", response2.message()); 2229e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 223071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl invalid = server.url("/invalid"); 2231e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response3 = get(invalid); 2232e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B", response3.body().string()); 2233e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(HttpURLConnection.HTTP_OK, response3.code()); 2234e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("B-OK", response3.message()); 2235e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response4 = get(invalid); 2236e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("C", response4.body().string()); 2237e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(HttpURLConnection.HTTP_OK, response4.code()); 2238e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("C-OK", response4.message()); 2239e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2240e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.takeRequest(); // regular get 2241e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return server.takeRequest(); // conditional get 2242e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2243e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2244e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void assertFullyCached(MockResponse response) throws Exception { 2245e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(response.setBody("A")); 2246e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(response.setBody("B")); 2247e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 224871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpUrl url = server.url("/"); 2249e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 2250e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("A", get(url).body().string()); 2251e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2252e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2253e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 2254e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Shortens the body of {@code response} but not the corresponding headers. 2255e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Only useful to test how clients respond to the premature conclusion of 2256e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * the HTTP body. 2257e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 2258e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) { 2259e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response.setSocketPolicy(DISCONNECT_AT_END); 2260e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Headers headers = response.getHeaders(); 2261e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer truncatedBody = new Buffer(); 2262e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller truncatedBody.write(response.getBody(), numBytesToKeep); 2263e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response.setBody(truncatedBody); 2264e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response.setHeaders(headers); 2265e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return response; 2266e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2267e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2268e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller enum TransferKind { 2269e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller CHUNKED() { 2270e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override void setBody(MockResponse response, Buffer content, int chunkSize) 2271e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller throws IOException { 2272e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response.setChunkedBody(content, chunkSize); 2273e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2274e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller }, 2275e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller FIXED_LENGTH() { 2276e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override void setBody(MockResponse response, Buffer content, int chunkSize) { 2277e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response.setBody(content); 2278e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2279e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller }, 2280e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller END_OF_STREAM() { 2281e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override void setBody(MockResponse response, Buffer content, int chunkSize) { 2282e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response.setBody(content); 2283e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response.setSocketPolicy(DISCONNECT_AT_END); 2284e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response.removeHeader("Content-Length"); 2285e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2286e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller }; 2287e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2288e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller abstract void setBody(MockResponse response, Buffer content, int chunkSize) throws IOException; 2289e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2290e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller void setBody(MockResponse response, String content, int chunkSize) throws IOException { 2291e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller setBody(response, new Buffer().writeUtf8(content), chunkSize); 2292e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2293e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2294e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2295e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** Returns a gzipped copy of {@code bytes}. */ 2296e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public Buffer gzip(String data) throws IOException { 2297e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer result = new Buffer(); 2298e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller BufferedSink sink = Okio.buffer(new GzipSink(result)); 2299e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller sink.writeUtf8(data); 2300e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller sink.close(); 2301e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return result; 2302e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2303e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller} 2304