HttpResponseCacheTest.java revision 757afaa7afe96791a3cc612c9e3c4597a7321c7e
10c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson/* 20c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Copyright (C) 2011 The Android Open Source Project 30c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 40c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 50c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * you may not use this file except in compliance with the License. 60c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * You may obtain a copy of the License at 70c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 80c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 90c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Unless required by applicable law or agreed to in writing, software 110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * See the License for the specific language governing permissions and 140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * limitations under the License. 150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 17757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilsonpackage libcore.net.http; 180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.io.BufferedReader; 200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.io.ByteArrayOutputStream; 21433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilsonimport java.io.File; 22c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilsonimport java.io.FileNotFoundException; 230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.io.IOException; 240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.io.InputStream; 250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.io.InputStreamReader; 260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.io.OutputStream; 270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.net.CacheRequest; 280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.net.CacheResponse; 290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.net.HttpURLConnection; 300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.net.ResponseCache; 310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.net.SecureCacheResponse; 320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.net.URI; 330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.net.URISyntaxException; 340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.net.URL; 350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.net.URLConnection; 360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.security.Principal; 370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.security.cert.Certificate; 38953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilsonimport java.text.DateFormat; 39953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilsonimport java.text.SimpleDateFormat; 400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.ArrayList; 410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.Arrays; 420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.Collections; 430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.Date; 440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.Iterator; 450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.List; 46953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilsonimport java.util.Locale; 470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.Map; 48953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilsonimport java.util.TimeZone; 49433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilsonimport java.util.UUID; 500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.concurrent.TimeUnit; 510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.concurrent.atomic.AtomicInteger; 520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.concurrent.atomic.AtomicReference; 530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport java.util.zip.GZIPOutputStream; 540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport javax.net.ssl.HttpsURLConnection; 550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport junit.framework.TestCase; 560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport libcore.javax.net.ssl.TestSSLContext; 570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport tests.http.MockResponse; 580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport tests.http.MockWebServer; 590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport tests.http.RecordedRequest; 600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonimport static tests.http.SocketPolicy.DISCONNECT_AT_END; 610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonpublic final class HttpResponseCacheTest extends TestCase { 630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private MockWebServer server = new MockWebServer(); 64433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson private HttpResponseCache cache; 650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override protected void setUp() throws Exception { 670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson super.setUp(); 68433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson 69433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson String tmp = System.getProperty("java.io.tmpdir"); 70433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson File cacheDir = new File(tmp, "HttpCache-" + UUID.randomUUID()); 71433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson cacheDir.mkdir(); 72433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE); 730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson ResponseCache.setDefault(cache); 740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override protected void tearDown() throws Exception { 770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.shutdown(); 78433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson ResponseCache.setDefault(null); 79433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson cache.delete(); 800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson super.tearDown(); 810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Test that response caching is consistent with the RI and the spec. 850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 8784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testResponseCachingByResponseCode() throws Exception { 880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // Test each documented HTTP/1.1 code, plus the first unused value in each range. 890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // We can't test 100 because it's not really a response. 920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // assertCached(false, 100); 930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, 101); 940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, 102); 950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(true, 200); 960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, 201); 970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, 202); 980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(true, 203); 990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, 204); 1000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, 205); 1010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(true, 206); 1020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, 207); 10384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertCached(true, 300); 1040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(true, 301); 1050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson for (int i = 302; i <= 308; ++i) { 1060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, i); 1070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 1080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson for (int i = 400; i <= 406; ++i) { 1090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, i); 1100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 1110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // (See test_responseCaching_407.) 1120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, 408); 1130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, 409); 1140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // (See test_responseCaching_410.) 1150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson for (int i = 411; i <= 418; ++i) { 1160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, i); 1170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 1180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson for (int i = 500; i <= 506; ++i) { 1190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertCached(false, i); 1200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 1210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 1220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 1240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Response code 407 should only come from proxy servers. Android's client 1250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * throws if it is sent by an origin server. 1260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 1270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testOriginServerSends407() throws Exception { 1280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setResponseCode(407)); 1290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 1300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 1320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 1330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson try { 1340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson conn.getResponseCode(); 1350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson fail(); 1360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } catch (IOException expected) { 1370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 1380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 1390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void test_responseCaching_410() throws Exception { 1410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // the HTTP spec permits caching 410s, but the RI doesn't. 14284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertCached(true, 410); 1430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 1440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void assertCached(boolean shouldPut, int responseCode) throws Exception { 1460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server = new MockWebServer(); 1470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 1480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 1500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setResponseCode(responseCode) 1510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setBody("ABCDE") 1520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("WWW-Authenticate: challenge")); 1530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 1540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 1560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 1570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(responseCode, conn.getResponseCode()); 1580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // exhaust the content stream 16084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson readAscii(conn); 1610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 162433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson CacheResponse cached = cache.get(url.toURI(), "GET", 163433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson Collections.<String, List<String>>emptyMap()); 164433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson if (shouldPut) { 165433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson assertNotNull(Integer.toString(responseCode), cached); 166433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson cached.getBody().close(); 167433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson } else { 168433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson assertNull(Integer.toString(responseCode), cached); 169433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson } 1700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers 1710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 1720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 1740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Test that we can interrogate the response when the cache is being 1750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * populated. http://code.google.com/p/android/issues/detail?id=7787 1760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 1770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testResponseCacheCallbackApis() throws Exception { 1780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson final String body = "ABCDE"; 1790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson final AtomicInteger cacheCount = new AtomicInteger(); 1800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 1820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setStatus("HTTP/1.1 200 Fantastic") 1830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("fgh: ijk") 1840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setBody(body)); 1850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 1860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson ResponseCache.setDefault(new ResponseCache() { 1880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public CacheResponse get(URI uri, String requestMethod, 1890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson Map<String, List<String>> requestHeaders) throws IOException { 1900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return null; 1910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 1920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException { 1930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpURLConnection httpConnection = (HttpURLConnection) conn; 194953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson try { 195953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson httpConnection.getRequestProperties(); 196953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson fail(); 197953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson } catch (IllegalStateException expected) { 198953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson } 199953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson try { 200953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson httpConnection.addRequestProperty("K", "V"); 201953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson fail(); 202953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson } catch (IllegalStateException expected) { 203953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson } 2040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("HTTP/1.1 200 Fantastic", httpConnection.getHeaderField(null)); 2050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(Arrays.asList("HTTP/1.1 200 Fantastic"), 2060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson httpConnection.getHeaderFields().get(null)); 2070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(200, httpConnection.getResponseCode()); 2080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("Fantastic", httpConnection.getResponseMessage()); 2090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(body.length(), httpConnection.getContentLength()); 2100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ijk", httpConnection.getHeaderField("fgh")); 2110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson try { 2120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson httpConnection.getInputStream(); // the RI doesn't forbid this, but it should 2130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson fail(); 2140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } catch (IOException expected) { 2150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 2160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson cacheCount.incrementAndGet(); 2170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return null; 2180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 2190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }); 2200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 222953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = url.openConnection(); 2230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(body, readAscii(connection)); 2240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cacheCount.get()); 2250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 2260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testResponseCachingAndInputStreamSkipWithFixedLength() throws IOException { 2290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testResponseCaching(TransferKind.FIXED_LENGTH); 2300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 2310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testResponseCachingAndInputStreamSkipWithChunkedEncoding() throws IOException { 2330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testResponseCaching(TransferKind.CHUNKED); 2340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 2350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testResponseCachingAndInputStreamSkipWithNoLengthHeaders() throws IOException { 2370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testResponseCaching(TransferKind.END_OF_STREAM); 2380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 2390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 2410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * HttpURLConnection.getInputStream().skip(long) causes ResponseCache corruption 2420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * http://code.google.com/p/android/issues/detail?id=8175 2430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 2440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void testResponseCaching(TransferKind transferKind) throws IOException { 2450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson MockResponse response = new MockResponse() 2460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 2470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 2480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setStatus("HTTP/1.1 200 Fantastic"); 2490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson transferKind.setBody(response, "I love puppies but hate spiders", 1); 2500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response); 2510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 2520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // Make sure that calling skip() doesn't omit bytes from the cache. 2540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpURLConnection urlConnection = (HttpURLConnection) server.getUrl("/").openConnection(); 2550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson InputStream in = urlConnection.getInputStream(); 2560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("I love ", readAscii(urlConnection, "I love ".length())); 2570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson reliableSkip(in, "puppies but hate ".length()); 2580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("spiders", readAscii(urlConnection, "spiders".length())); 2590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(-1, in.read()); 2600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson in.close(); 2610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cache.getSuccessCount()); 2620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(0, cache.getAbortCount()); 2630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2640c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson urlConnection = (HttpURLConnection) server.getUrl("/").openConnection(); // cached! 2650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson in = urlConnection.getInputStream(); 2660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("I love puppies but hate spiders", 2670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson readAscii(urlConnection, "I love puppies but hate spiders".length())); 2680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(200, urlConnection.getResponseCode()); 2690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("Fantastic", urlConnection.getResponseMessage()); 2700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(-1, in.read()); 272433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson in.close(); 2730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cache.getMissCount()); 274757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(1, cache.getHeadersHitCount()); 2750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cache.getSuccessCount()); 2760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(0, cache.getAbortCount()); 2770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 2780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testSecureResponseCaching() throws IOException { 2800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 2810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 2820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 2830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 2840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 2850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setBody("ABC")); 2860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 2870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 2890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 2900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 2910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // OpenJDK 6 fails on this line, complaining that the connection isn't open yet 2930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String suite = connection.getCipherSuite(); 2940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<Certificate> localCerts = toListOrNull(connection.getLocalCertificates()); 2950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<Certificate> serverCerts = toListOrNull(connection.getServerCertificates()); 2960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson Principal peerPrincipal = connection.getPeerPrincipal(); 2970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson Principal localPrincipal = connection.getLocalPrincipal(); 2980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 2990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached! 3000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 3010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 3020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cache.getMissCount()); 304757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(1, cache.getHeadersHitCount()); 3050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(suite, connection.getCipherSuite()); 3070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(localCerts, toListOrNull(connection.getLocalCertificates())); 3080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(serverCerts, toListOrNull(connection.getServerCertificates())); 3090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(peerPrincipal, connection.getPeerPrincipal()); 3100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(localPrincipal, connection.getLocalPrincipal()); 3110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 3120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testCacheReturnsInsecureResponseForSecureRequest() throws IOException { 3140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 3150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 3160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("ABC")); 3170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("DEF")); 3180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 3190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson ResponseCache.setDefault(new InsecureResponseCache()); 3210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 3230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 3240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 3250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // not cached! 3270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 3280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("DEF", readAscii(connection)); 3290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 3300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 331a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson public void testResponseCachingAndRedirects() throws Exception { 3320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 3330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 3360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Location: /foo")); 3370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 3380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setBody("ABC")); 3410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("DEF")); 3420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 3430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 344953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 3450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 3460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 347953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson connection = server.getUrl("/").openConnection(); // cached! 3480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 3490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(2, cache.getMissCount()); // 1 redirect + 1 final response = 2 351757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(2, cache.getHeadersHitCount()); 3520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 3530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 354a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson public void testRedirectToCachedResult() throws Exception { 355a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson server.enqueue(new MockResponse() 356a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson .addHeader("Cache-Control: max-age=60") 357a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson .setBody("ABC")); 358a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson server.enqueue(new MockResponse() 359a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 360a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson .addHeader("Location: /foo")); 361a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson server.enqueue(new MockResponse().setBody("DEF")); 362a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson server.play(); 363a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson 364a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("ABC", readAscii(server.getUrl("/foo").openConnection())); 365a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson RecordedRequest request1 = server.takeRequest(); 366a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("GET /foo HTTP/1.1", request1.getRequestLine()); 367a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals(0, request1.getSequenceNumber()); 368a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson 369a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("ABC", readAscii(server.getUrl("/bar").openConnection())); 370a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson RecordedRequest request2 = server.takeRequest(); 371a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("GET /bar HTTP/1.1", request2.getRequestLine()); 372a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals(1, request2.getSequenceNumber()); 373a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson 374a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson // an unrelated request should reuse the pooled connection 375a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("DEF", readAscii(server.getUrl("/baz").openConnection())); 376a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson RecordedRequest request3 = server.takeRequest(); 377a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("GET /baz HTTP/1.1", request3.getRequestLine()); 378a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals(2, request3.getSequenceNumber()); 379a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson } 380a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson 3810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testSecureResponseCachingAndRedirects() throws IOException { 3820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 3830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 3840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 3850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 3880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Location: /foo")); 3890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 3900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setBody("ABC")); 3930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("DEF")); 3940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 3950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 3970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 3980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 3990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached! 4010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 4020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 4030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(2, cache.getMissCount()); // 1 redirect + 1 final response = 2 405757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(2, cache.getHeadersHitCount()); 4060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testResponseCacheRequestHeaders() throws IOException, URISyntaxException { 4090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("ABC")); 4100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 4110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson final AtomicReference<Map<String, List<String>>> requestHeadersRef 4130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson = new AtomicReference<Map<String, List<String>>>(); 4140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson ResponseCache.setDefault(new ResponseCache() { 4150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public CacheResponse get(URI uri, String requestMethod, 4160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson Map<String, List<String>> requestHeaders) throws IOException { 4170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson requestHeadersRef.set(requestHeaders); 4180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return null; 4190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException { 4210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return null; 4220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }); 4240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 4260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URLConnection urlConnection = url.openConnection(); 4270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson urlConnection.addRequestProperty("A", "android"); 4280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson readAscii(urlConnection); 4290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(Arrays.asList("android"), requestHeadersRef.get().get("A")); 4300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testServerDisconnectsPrematurelyWithContentLengthHeader() throws IOException { 4340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testServerPrematureDisconnect(TransferKind.FIXED_LENGTH); 4350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testServerDisconnectsPrematurelyWithChunkedEncoding() throws IOException { 4380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testServerPrematureDisconnect(TransferKind.CHUNKED); 4390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testServerDisconnectsPrematurelyWithNoLengthHeaders() throws IOException { 4420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /* 4430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Intentionally empty. This case doesn't make sense because there's no 4440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * such thing as a premature disconnect when the disconnect itself 4450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * indicates the end of the data stream. 4460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 4470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException { 4500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson MockResponse response = new MockResponse(); 4510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 16); 4520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(truncateViolently(response, 16)); 4530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("Request #2")); 4540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 4550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson BufferedReader reader = new BufferedReader(new InputStreamReader( 4570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.getUrl("/").openConnection().getInputStream())); 4580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABCDE", reader.readLine()); 4590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson try { 4600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson reader.readLine(); 4610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson fail("This implementation silently ignored a truncated HTTP body."); 4620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } catch (IOException expected) { 463433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson } finally { 464433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson reader.close(); 4650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cache.getAbortCount()); 4680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(0, cache.getSuccessCount()); 4690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 4700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("Request #2", readAscii(connection)); 4710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cache.getAbortCount()); 4720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cache.getSuccessCount()); 4730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testClientPrematureDisconnectWithContentLengthHeader() throws IOException { 4760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testClientPrematureDisconnect(TransferKind.FIXED_LENGTH); 4770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testClientPrematureDisconnectWithChunkedEncoding() throws IOException { 4800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testClientPrematureDisconnect(TransferKind.CHUNKED); 4810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testClientPrematureDisconnectWithNoLengthHeaders() throws IOException { 4840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testClientPrematureDisconnect(TransferKind.END_OF_STREAM); 4850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException { 4880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson MockResponse response = new MockResponse(); 4890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 1024); 4900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response); 4910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("Request #2")); 4920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 4930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 4950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson InputStream in = connection.getInputStream(); 4960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABCDE", readAscii(connection, 5)); 4970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson in.close(); 4980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson try { 4990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson in.read(); 5000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson fail("Expected an IOException because the stream is closed."); 5010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } catch (IOException expected) { 5020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 5040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cache.getAbortCount()); 5050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(0, cache.getSuccessCount()); 5060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection = server.getUrl("/").openConnection(); 50784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("Request #2", readAscii(connection)); 5080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cache.getAbortCount()); 5090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(1, cache.getSuccessCount()); 5100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 512953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson public void testDefaultExpirationDateFullyCachedForLessThan24Hours() throws Exception { 51321dddca4064527116af7a1553de502c6d11138daJesse Wilson // last modified: 105 seconds ago 51421dddca4064527116af7a1553de502c6d11138daJesse Wilson // served: 5 seconds ago 51521dddca4064527116af7a1553de502c6d11138daJesse Wilson // default lifetime: (105 - 5) / 10 = 10 seconds 51621dddca4064527116af7a1553de502c6d11138daJesse Wilson // expires: 10 seconds from served date = 5 seconds from now 517953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse() 51821dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS)) 519953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS)) 520953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .setBody("A")); 521953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.play(); 522953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 523953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URL url = server.getUrl("/"); 524953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 525953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = url.openConnection(); 526953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(connection)); 527953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertNull(connection.getHeaderField("Warning")); 52821dddca4064527116af7a1553de502c6d11138daJesse Wilson } 52921dddca4064527116af7a1553de502c6d11138daJesse Wilson 53021dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testDefaultExpirationDateConditionallyCached() throws Exception { 53121dddca4064527116af7a1553de502c6d11138daJesse Wilson // last modified: 115 seconds ago 53221dddca4064527116af7a1553de502c6d11138daJesse Wilson // served: 15 seconds ago 53321dddca4064527116af7a1553de502c6d11138daJesse Wilson // default lifetime: (115 - 15) / 10 = 10 seconds 53421dddca4064527116af7a1553de502c6d11138daJesse Wilson // expires: 10 seconds from served date = 5 seconds ago 53521dddca4064527116af7a1553de502c6d11138daJesse Wilson String lastModifiedDate = formatDate(-115, TimeUnit.SECONDS); 5360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 53721dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 53821dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Date: " + formatDate(-15, TimeUnit.SECONDS))); 5390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 5400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 5410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 543953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson public void testDefaultExpirationDateFullyCachedForMoreThan24Hours() throws Exception { 544953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson // last modified: 105 days ago 545953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson // served: 5 days ago 546953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson // default lifetime: (105 - 5) / 10 = 10 days 547953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson // expires: 10 days from served date = 5 days from now 548953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse() 549953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.DAYS)) 550953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Date: " + formatDate(-5, TimeUnit.DAYS)) 551953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .setBody("A")); 552953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.play(); 553953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 554953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 555953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 556953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(connection)); 557953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("113 HttpURLConnection \"Heuristic expiration\"", 558953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson connection.getHeaderField("Warning")); 559953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson } 560953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 56121dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testNoDefaultExpirationForUrlsWithQueryString() throws Exception { 56221dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(new MockResponse() 56321dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS)) 56421dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS)) 56521dddca4064527116af7a1553de502c6d11138daJesse Wilson .setBody("A")); 56621dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(new MockResponse().setBody("B")); 56721dddca4064527116af7a1553de502c6d11138daJesse Wilson server.play(); 56821dddca4064527116af7a1553de502c6d11138daJesse Wilson 56921dddca4064527116af7a1553de502c6d11138daJesse Wilson URL url = server.getUrl("/?foo=bar"); 57021dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("A", readAscii(url.openConnection())); 57121dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("B", readAscii(url.openConnection())); 57221dddca4064527116af7a1553de502c6d11138daJesse Wilson } 57321dddca4064527116af7a1553de502c6d11138daJesse Wilson 5740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testExpirationDateInThePastWithLastModifiedHeader() throws Exception { 5750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 5760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 5770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 5780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 5790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 5800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 5810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 5830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testExpirationDateInThePastWithNoLastModifiedHeader() throws Exception { 5840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse() 5850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 5860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 5880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testExpirationDateInTheFuture() throws Exception { 5890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertFullyCached(new MockResponse() 5900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 5910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 5930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testMaxAgePreferredWithMaxAgeAndExpires() throws Exception { 5940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertFullyCached(new MockResponse() 5950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.HOURS)) 5960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)) 5970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: max-age=60")); 5980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testMaxAgeInThePastWithDateAndLastModifiedHeaders() throws Exception { 6010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 6020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 6030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS)) 6040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 6050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: max-age=60")); 6060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 6070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 6080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testMaxAgeInThePastWithDateHeaderButNoLastModifiedHeader() throws Exception { 61184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson /* 61284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson * Chrome interprets max-age relative to the local clock. Both our cache 61384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson * and Firefox both use the earlier of the local and server's clock. 61484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson */ 6150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse() 6160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS)) 6170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: max-age=60")); 6180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testMaxAgeInTheFutureWithDateHeader() throws Exception { 6210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertFullyCached(new MockResponse() 6220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.HOURS)) 6230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: max-age=60")); 6240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testMaxAgeInTheFutureWithNoDateHeader() throws Exception { 6270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertFullyCached(new MockResponse() 6280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: max-age=60")); 6290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 631adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson public void testMaxAgeWithLastModifiedButNoServedDate() throws Exception { 632adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertFullyCached(new MockResponse() 633adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 634adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Cache-Control: max-age=60")); 635adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson } 636adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 637adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson public void testMaxAgeInTheFutureWithDateAndLastModifiedHeaders() throws Exception { 638adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertFullyCached(new MockResponse() 639adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 640adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 641adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Cache-Control: max-age=60")); 642adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson } 643adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 64421dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testMaxAgePreferredOverLowerSharedMaxAge() throws Exception { 64521dddca4064527116af7a1553de502c6d11138daJesse Wilson assertFullyCached(new MockResponse() 64621dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 64721dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: s-maxage=60") 64821dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: max-age=180")); 64921dddca4064527116af7a1553de502c6d11138daJesse Wilson } 65021dddca4064527116af7a1553de502c6d11138daJesse Wilson 65121dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testMaxAgePreferredOverHigherMaxAge() throws Exception { 65221dddca4064527116af7a1553de502c6d11138daJesse Wilson assertNotCached(new MockResponse() 65321dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 65421dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: s-maxage=180") 65521dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: max-age=60")); 65621dddca4064527116af7a1553de502c6d11138daJesse Wilson } 65721dddca4064527116af7a1553de502c6d11138daJesse Wilson 6580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodOptionsIsNotCached() throws Exception { 6590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("OPTIONS", false); 6600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodGetIsCached() throws Exception { 6630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("GET", true); 6640c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodHeadIsNotCached() throws Exception { 6670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // We could support this but choose not to for implementation simplicity 6680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("HEAD", false); 6690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodPostIsNotCached() throws Exception { 6720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // We could support this but choose not to for implementation simplicity 6730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("POST", false); 6740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodPutIsNotCached() throws Exception { 6770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("PUT", false); 6780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodDeleteIsNotCached() throws Exception { 6810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("DELETE", false); 6820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodTraceIsNotCached() throws Exception { 6850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("TRACE", false); 6860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void testRequestMethod(String requestMethod, boolean expectCached) throws Exception { 6890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /* 6900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 1. seed the cache (potentially) 6910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 2. expect a cache hit or miss 6920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 6930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 6940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 6950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("X-Response-ID: 1")); 6960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 6970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("X-Response-ID: 2")); 6980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 6990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 7010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpURLConnection request1 = (HttpURLConnection) url.openConnection(); 7030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson request1.setRequestMethod(requestMethod); 7040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson addRequestBodyIfNecessary(requestMethod, request1); 7050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("1", request1.getHeaderField("X-Response-ID")); 7060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 707953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection request2 = url.openConnection(); 7080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson if (expectCached) { 7090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("1", request1.getHeaderField("X-Response-ID")); 7100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } else { 7110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("2", request2.getHeaderField("X-Response-ID")); 7120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testPostInvalidatesCache() throws Exception { 7160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testMethodInvalidates("POST"); 7170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testPutInvalidatesCache() throws Exception { 7200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testMethodInvalidates("PUT"); 7210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testDeleteMethodInvalidatesCache() throws Exception { 7240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testMethodInvalidates("DELETE"); 7250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void testMethodInvalidates(String requestMethod) throws Exception { 7280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /* 7290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 1. seed the cache 7300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 2. invalidate it 7310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 3. expect a cache miss 7320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 7330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("A") 7340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 7350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 7360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("C")); 7370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 7380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 7400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 7420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpURLConnection invalidate = (HttpURLConnection) url.openConnection(); 7440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson invalidate.setRequestMethod(requestMethod); 7450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson addRequestBodyIfNecessary(requestMethod, invalidate); 7460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("B", readAscii(invalidate)); 7470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("C", readAscii(url.openConnection())); 7490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testEtag() throws Exception { 7520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 7530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("ETag: v1")); 7540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(conditionalRequest.getHeaders().contains("If-None-Match: v1")); 7550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testEtagAndExpirationDateInThePast() throws Exception { 7580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 7590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 7600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("ETag: v1") 7610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 7620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 7630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 7640c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-None-Match: v1")); 7650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 7660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testEtagAndExpirationDateInTheFuture() throws Exception { 7690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertFullyCached(new MockResponse() 7700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("ETag: v1") 7710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 7720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 7730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testCacheControlNoCache() throws Exception { 7760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse().addHeader("Cache-Control: no-cache")); 7770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testCacheControlNoCacheAndExpirationDateInTheFuture() throws Exception { 7800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 7810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 7820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 7830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 7840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: no-cache")); 7850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 7860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 7870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testPragmaNoCache() throws Exception { 7900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse().addHeader("Pragma: no-cache")); 7910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testPragmaNoCacheAndExpirationDateInTheFuture() throws Exception { 7940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 7950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 7960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 7970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 7980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Pragma: no-cache")); 7990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 8000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 8010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testCacheControlNoStore() throws Exception { 8040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse().addHeader("Cache-Control: no-store")); 8050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testCacheControlNoStoreAndExpirationDateInTheFuture() throws Exception { 8080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse() 8090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 8110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: no-store")); 8120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testPartialRangeResponsesDoNotCorruptCache() throws Exception { 8150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /* 8160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 1. request a range 8170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 2. request a full document, expecting a cache miss 8180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 8190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("AA") 8200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setResponseCode(HttpURLConnection.HTTP_PARTIAL) 8210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 8220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Content-Range: bytes 1000-1001/2000")); 8230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("BB")); 8240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 8250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 8270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URLConnection range = url.openConnection(); 8290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson range.addRequestProperty("Range", "bytes=1000-1001"); 8300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("AA", readAscii(range)); 8310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("BB", readAscii(url.openConnection())); 8330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testServerReturnsDocumentOlderThanCache() throws Exception { 8360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("A") 8370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 8390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("B") 8400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-4, TimeUnit.HOURS))); 8410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 8420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 8440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 8460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 8470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testNonIdentityEncodingAndConditionalCache() throws Exception { 8500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNonIdentityEncodingCached(new MockResponse() 8510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 8530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testNonIdentityEncodingAndFullCache() throws Exception { 8560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNonIdentityEncodingCached(new MockResponse() 8570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 8590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void assertNonIdentityEncodingCached(MockResponse response) throws Exception { 8620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response 8630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setBody(gzip("ABCABCABC".getBytes("UTF-8"))) 8640c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Content-Encoding: gzip")); 8650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 8660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 8680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABCABCABC", readAscii(server.getUrl("/").openConnection())); 8690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABCABCABC", readAscii(server.getUrl("/").openConnection())); 8700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testExpiresDateBeforeModifiedDate() throws Exception { 8730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertConditionallyCached(new MockResponse() 8740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 8750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-2, TimeUnit.HOURS))); 8760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 878adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson public void testRequestMaxAge() throws IOException { 879adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.enqueue(new MockResponse().setBody("A") 880adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 881adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES)) 882adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 883adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 884adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 885adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.play(); 886adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 887adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 888adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 889adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson connection.addRequestProperty("Cache-Control", "max-age=30"); 890adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertEquals("B", readAscii(connection)); 891adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson } 892adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 893adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson public void testRequestMinFresh() throws IOException { 894adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.enqueue(new MockResponse().setBody("A") 895adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Cache-Control: max-age=60") 896adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 897adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 898adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 899adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.play(); 900adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 901adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 902adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 903adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson connection.addRequestProperty("Cache-Control", "min-fresh=120"); 904adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertEquals("B", readAscii(connection)); 905adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson } 906adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 907c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson public void testRequestMaxStale() throws IOException { 908c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.enqueue(new MockResponse().setBody("A") 909c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Cache-Control: max-age=120") 910c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES))); 911c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.enqueue(new MockResponse().setBody("B")); 912c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 913c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.play(); 914c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 915c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 916c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 917c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.addRequestProperty("Cache-Control", "max-stale=180"); 918c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(connection)); 919953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("110 HttpURLConnection \"Response is stale\"", 920953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson connection.getHeaderField("Warning")); 921c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 922c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 9232f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson public void testRequestMaxStaleNotHonoredWithMustRevalidate() throws IOException { 9242f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.enqueue(new MockResponse().setBody("A") 9252f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson .addHeader("Cache-Control: max-age=120, must-revalidate") 9262f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES))); 9272f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 9282f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 9292f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.play(); 9302f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 9312f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 9322f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 9332f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson connection.addRequestProperty("Cache-Control", "max-stale=180"); 9342f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals("B", readAscii(connection)); 9352f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson } 9362f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 937c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson public void testRequestOnlyIfCachedWithNoResponseCached() throws IOException { 938c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson // (no responses enqueued) 939c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.play(); 940c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 941953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 942c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.addRequestProperty("Cache-Control", "only-if-cached"); 943c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertBadGateway(connection); 944c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 945c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 946c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson public void testRequestOnlyIfCachedWithFullResponseCached() throws IOException { 947c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.enqueue(new MockResponse().setBody("A") 948c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Cache-Control: max-age=30") 949c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 950c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.play(); 951c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 952c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 953c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 954c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.addRequestProperty("Cache-Control", "only-if-cached"); 955c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 956c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 957c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 958c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson public void testRequestOnlyIfCachedWithConditionalResponseCached() throws IOException { 959c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.enqueue(new MockResponse().setBody("A") 960c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Cache-Control: max-age=30") 961c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES))); 962c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.play(); 963c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 964c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 965953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 966c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.addRequestProperty("Cache-Control", "only-if-cached"); 967c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertBadGateway(connection); 968c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 969c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 970c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson public void testRequestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException { 971c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.enqueue(new MockResponse().setBody("A")); 972c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.play(); 973c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 974c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 975953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 976c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.addRequestProperty("Cache-Control", "only-if-cached"); 977c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertBadGateway(connection); 978c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 979c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 98084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testRequestCacheControlNoCache() throws Exception { 98184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse() 98284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 98384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 98484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Cache-Control: max-age=60") 98584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .setBody("A")); 98684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 98784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.play(); 98884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 98984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson URL url = server.getUrl("/"); 99084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 99184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson URLConnection connection = url.openConnection(); 99284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson connection.setRequestProperty("Cache-Control", "no-cache"); 99384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("B", readAscii(connection)); 99484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 99584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 99684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testRequestPragmaNoCache() throws Exception { 99784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse() 99884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 99984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 100084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Cache-Control: max-age=60") 100184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .setBody("A")); 100284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 100384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.play(); 100484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 100584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson URL url = server.getUrl("/"); 100684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 100784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson URLConnection connection = url.openConnection(); 100884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson connection.setRequestProperty("Pragma", "no-cache"); 100984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("B", readAscii(connection)); 101084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 101184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 101284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testClientSuppliedIfModifiedSinceWithCachedResult() throws Exception { 101384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson MockResponse response = new MockResponse() 101484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("ETag: v3") 101584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Cache-Control: max-age=0"); 101684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson String ifModifiedSinceDate = formatDate(-24, TimeUnit.HOURS); 101784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson RecordedRequest request = assertClientSuppliedCondition( 101884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson response, "If-Modified-Since", ifModifiedSinceDate); 101984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson List<String> headers = request.getHeaders(); 102084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + ifModifiedSinceDate)); 102184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertFalse(headers.contains("If-None-Match: v3")); 102284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 102384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 102484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testClientSuppliedIfNoneMatchSinceWithCachedResult() throws Exception { 102584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson String lastModifiedDate = formatDate(-3, TimeUnit.MINUTES); 102684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson MockResponse response = new MockResponse() 102784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 102884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 102984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Cache-Control: max-age=0"); 103084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson RecordedRequest request = assertClientSuppliedCondition( 103184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson response, "If-None-Match", "v1"); 103284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson List<String> headers = request.getHeaders(); 103384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertTrue(headers.contains("If-None-Match: v1")); 103484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertFalse(headers.contains("If-Modified-Since: " + lastModifiedDate)); 103584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 103684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 103784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson private RecordedRequest assertClientSuppliedCondition(MockResponse seed, String conditionName, 103884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson String conditionValue) throws Exception { 103984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(seed.setBody("A")); 104084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 104184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.play(); 104284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 104384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson URL url = server.getUrl("/"); 104484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 104584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 104684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 104784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson connection.addRequestProperty(conditionName, conditionValue); 104884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode()); 104984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("", readAscii(connection)); 105084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 105184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.takeRequest(); // seed 105284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson return server.takeRequest(); 105384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 105484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 10559531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson public void testSetIfModifiedSince() throws Exception { 10569531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson Date since = new Date(); 10579531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson server.enqueue(new MockResponse().setBody("A")); 10589531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson server.play(); 10599531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson 10609531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson URL url = server.getUrl("/"); 10619531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson URLConnection connection = url.openConnection(); 10629531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson connection.setIfModifiedSince(since.getTime()); 10639531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson assertEquals("A", readAscii(connection)); 10649531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson RecordedRequest request = server.takeRequest(); 10659531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson assertTrue(request.getHeaders().contains("If-Modified-Since: " + formatDate(since))); 10669531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson } 10679531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson 106884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testClientSuppliedConditionWithoutCachedResult() throws Exception { 106984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse() 107084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 107184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.play(); 107284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 107384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 107484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson String clientIfModifiedSince = formatDate(-24, TimeUnit.HOURS); 107584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson connection.addRequestProperty("If-Modified-Since", clientIfModifiedSince); 107684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode()); 107784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("", readAscii(connection)); 107884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 1079c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 108021dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testAuthorizationRequestHeaderPreventsCaching() throws Exception { 108121dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(new MockResponse() 108221dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.MINUTES)) 108321dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: max-age=60") 108421dddca4064527116af7a1553de502c6d11138daJesse Wilson .setBody("A")); 108521dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(new MockResponse().setBody("B")); 108621dddca4064527116af7a1553de502c6d11138daJesse Wilson server.play(); 108721dddca4064527116af7a1553de502c6d11138daJesse Wilson 108821dddca4064527116af7a1553de502c6d11138daJesse Wilson URL url = server.getUrl("/"); 1089953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = url.openConnection(); 109021dddca4064527116af7a1553de502c6d11138daJesse Wilson connection.addRequestProperty("Authorization", "password"); 109121dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("A", readAscii(connection)); 109221dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("B", readAscii(url.openConnection())); 109321dddca4064527116af7a1553de502c6d11138daJesse Wilson } 109421dddca4064527116af7a1553de502c6d11138daJesse Wilson 109521dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testAuthorizationResponseCachedWithSMaxAge() throws Exception { 109621dddca4064527116af7a1553de502c6d11138daJesse Wilson assertAuthorizationRequestFullyCached(new MockResponse() 109721dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: s-maxage=60")); 109821dddca4064527116af7a1553de502c6d11138daJesse Wilson } 109921dddca4064527116af7a1553de502c6d11138daJesse Wilson 110021dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testAuthorizationResponseCachedWithPublic() throws Exception { 110121dddca4064527116af7a1553de502c6d11138daJesse Wilson assertAuthorizationRequestFullyCached(new MockResponse() 110221dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: public")); 110321dddca4064527116af7a1553de502c6d11138daJesse Wilson } 110421dddca4064527116af7a1553de502c6d11138daJesse Wilson 110521dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testAuthorizationResponseCachedWithMustRevalidate() throws Exception { 110621dddca4064527116af7a1553de502c6d11138daJesse Wilson assertAuthorizationRequestFullyCached(new MockResponse() 110721dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: must-revalidate")); 110821dddca4064527116af7a1553de502c6d11138daJesse Wilson } 110921dddca4064527116af7a1553de502c6d11138daJesse Wilson 111021dddca4064527116af7a1553de502c6d11138daJesse Wilson public void assertAuthorizationRequestFullyCached(MockResponse response) throws Exception { 111121dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(response 111221dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: max-age=60") 111321dddca4064527116af7a1553de502c6d11138daJesse Wilson .setBody("A")); 111421dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(new MockResponse().setBody("B")); 111521dddca4064527116af7a1553de502c6d11138daJesse Wilson server.play(); 111621dddca4064527116af7a1553de502c6d11138daJesse Wilson 111721dddca4064527116af7a1553de502c6d11138daJesse Wilson URL url = server.getUrl("/"); 1118953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = url.openConnection(); 111921dddca4064527116af7a1553de502c6d11138daJesse Wilson connection.addRequestProperty("Authorization", "password"); 112021dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("A", readAscii(connection)); 112121dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("A", readAscii(url.openConnection())); 112221dddca4064527116af7a1553de502c6d11138daJesse Wilson } 112321dddca4064527116af7a1553de502c6d11138daJesse Wilson 1124953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson public void testVaryResponsesAreNotSupported() throws Exception { 1125953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse() 1126953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Cache-Control: max-age=60") 1127953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Vary: Accept-Language") 1128953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .setBody("A")); 1129953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 1130953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.play(); 1131953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 1132953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URL url = server.getUrl("/"); 1133953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection1 = url.openConnection(); 1134953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson connection1.addRequestProperty("Accept-Language", "fr-CA"); 1135953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(connection1)); 1136953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 1137953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection2 = url.openConnection(); 1138953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson connection2.addRequestProperty("Accept-Language", "fr-CA"); 1139953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("B", readAscii(connection2)); 1140953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson } 1141953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 1142953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson public void testContentLocationDoesNotPopulateCache() throws Exception { 1143953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse() 1144953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Cache-Control: max-age=60") 1145953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Content-Location: /bar") 1146953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .setBody("A")); 1147953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 1148953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.play(); 1149953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 1150953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(server.getUrl("/foo").openConnection())); 1151953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("B", readAscii(server.getUrl("/bar").openConnection())); 1152953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson } 1153953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 115419c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson public void testUseCachesFalseDoesNotWriteToCache() throws Exception { 115519c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.enqueue(new MockResponse() 115619c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson .addHeader("Cache-Control: max-age=60") 115719c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson .setBody("A").setBody("A")); 115819c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 115919c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.play(); 116019c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson 116119c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 116219c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson connection.setUseCaches(false); 116319c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertEquals("A", readAscii(connection)); 116419c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertEquals("B", readAscii(server.getUrl("/").openConnection())); 116519c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson } 116619c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson 116719c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson public void testUseCachesFalseDoesNotReadFromCache() throws Exception { 116819c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.enqueue(new MockResponse() 116919c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson .addHeader("Cache-Control: max-age=60") 117019c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson .setBody("A").setBody("A")); 117119c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 117219c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.play(); 117319c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson 117419c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 117519c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 117619c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson connection.setUseCaches(false); 117719c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertEquals("B", readAscii(connection)); 117819c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson } 117919c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson 118019c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson public void testDefaultUseCachesSetsInitialValueOnly() throws Exception { 118119c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URL url = new URL("http://localhost/"); 118219c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URLConnection c1 = url.openConnection(); 118319c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URLConnection c2 = url.openConnection(); 118419c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertTrue(c1.getDefaultUseCaches()); 118519c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson c1.setDefaultUseCaches(false); 118619c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson try { 118719c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertTrue(c1.getUseCaches()); 118819c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertTrue(c2.getUseCaches()); 118919c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URLConnection c3 = url.openConnection(); 119019c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertFalse(c3.getUseCaches()); 119119c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson } finally { 119219c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson c1.setDefaultUseCaches(true); 119319c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson } 119419c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson } 119519c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson 11962f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson public void testConnectionIsReturnedToPoolAfterConditionalSuccess() throws Exception { 11972f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.enqueue(new MockResponse() 11982f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 11992f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson .addHeader("Cache-Control: max-age=0") 12002f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson .setBody("A")); 12012f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 12022f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 12032f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.play(); 12042f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 12052f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals("A", readAscii(server.getUrl("/a").openConnection())); 12062f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals("A", readAscii(server.getUrl("/a").openConnection())); 12072f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals("B", readAscii(server.getUrl("/b").openConnection())); 12082f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 12092f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals(0, server.takeRequest().getSequenceNumber()); 12102f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals(1, server.takeRequest().getSequenceNumber()); 12112f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals(2, server.takeRequest().getSequenceNumber()); 12122f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson } 12132f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 1214757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson public void testStatisticsConditionalCacheMiss() throws Exception { 1215757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse() 1216757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1217757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .addHeader("Cache-Control: max-age=0") 1218757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .setBody("A")); 1219757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse().setBody("B")); 1220757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse().setBody("C")); 1221757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.play(); 1222757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 1223757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1224757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(1, cache.getMissCount()); 1225757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(0, cache.getHeadersHitCount()); 1226757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(0, cache.getBodyHitCount()); 1227757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("B", readAscii(server.getUrl("/").openConnection())); 1228757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("C", readAscii(server.getUrl("/").openConnection())); 1229757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(1, cache.getMissCount()); 1230757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(2, cache.getHeadersHitCount()); 1231757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(0, cache.getBodyHitCount()); 1232757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson } 1233757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 1234757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson public void testStatisticsConditionalCacheHit() throws Exception { 1235757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse() 1236757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1237757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .addHeader("Cache-Control: max-age=0") 1238757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .setBody("A")); 1239757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1240757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1241757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.play(); 1242757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 1243757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1244757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(1, cache.getMissCount()); 1245757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(0, cache.getHeadersHitCount()); 1246757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(0, cache.getBodyHitCount()); 1247757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1248757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1249757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(1, cache.getMissCount()); 1250757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(2, cache.getHeadersHitCount()); 1251757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(2, cache.getBodyHitCount()); 1252757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson } 1253757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 1254757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson public void testStatisticsFullCacheHit() throws Exception { 1255757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse() 1256757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .addHeader("Cache-Control: max-age=60") 1257757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .setBody("A")); 1258757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.play(); 1259757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 1260757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1261757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(1, cache.getMissCount()); 1262757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(0, cache.getHeadersHitCount()); 1263757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(0, cache.getBodyHitCount()); 1264757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1265757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1266757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(1, cache.getMissCount()); 1267757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(2, cache.getHeadersHitCount()); 1268757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals(2, cache.getBodyHitCount()); 1269757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson } 1270757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 12710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 12720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * @param delta the offset from the current date to use. Negative 12730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * values yield dates in the past; positive values yield dates in the 12740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * future. 12750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 1276953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson private String formatDate(long delta, TimeUnit timeUnit) { 12779531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta))); 12789531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson } 12799531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson 12809531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson private String formatDate(Date date) { 1281953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); 1282953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson rfc1123.setTimeZone(TimeZone.getTimeZone("UTC")); 1283953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson return rfc1123.format(date); 12840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 12850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 12860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void addRequestBodyIfNecessary(String requestMethod, HttpURLConnection invalidate) 12870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson throws IOException { 12880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson if (requestMethod.equals("POST") || requestMethod.equals("PUT")) { 12890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson invalidate.setDoOutput(true); 12900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson OutputStream requestBody = invalidate.getOutputStream(); 12910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson requestBody.write('x'); 12920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson requestBody.close(); 12930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 12940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 12950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 12960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void assertNotCached(MockResponse response) throws Exception { 12970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response.setBody("A")); 12980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 12990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 13000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 13020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 13030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("B", readAscii(url.openConnection())); 13040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 13070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * @return the request with the conditional get headers. 13080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 13090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private RecordedRequest assertConditionallyCached(MockResponse response) throws Exception { 13100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // scenario 1: condition succeeds 13110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response.setBody("A")); 13120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 13130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // scenario 2: condition fails 13150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response.setBody("B")); 13160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("C")); 13170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 13190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL valid = server.getUrl("/valid"); 13210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(valid.openConnection())); 13220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(valid.openConnection())); 13230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL invalid = server.getUrl("/invalid"); 13250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("B", readAscii(invalid.openConnection())); 13260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("C", readAscii(invalid.openConnection())); 13270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.takeRequest(); // regular get 13290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return server.takeRequest(); // conditional get 13300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void assertFullyCached(MockResponse response) throws Exception { 13330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response.setBody("A")); 13340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response.setBody("B")); 13350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 13360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 13380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 13390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 13400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 13430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Shortens the body of {@code response} but not the corresponding headers. 13440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Only useful to test how clients respond to the premature conclusion of 13450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * the HTTP body. 13460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 13470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) { 13480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setSocketPolicy(DISCONNECT_AT_END); 13490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = new ArrayList<String>(response.getHeaders()); 13500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setBody(Arrays.copyOfRange(response.getBody(), 0, numBytesToKeep)); 13510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.getHeaders().clear(); 13520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.getHeaders().addAll(headers); 13530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return response; 13540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 13570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Reads {@code count} characters from the stream. If the stream is 13580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * exhausted before {@code count} characters can be read, the remaining 13590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * characters are returned and the stream is closed. 13600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 13610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private String readAscii(URLConnection connection, int count) throws IOException { 136284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson HttpURLConnection httpConnection = (HttpURLConnection) connection; 136384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson InputStream in = httpConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST 136484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson ? connection.getInputStream() 136584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson : httpConnection.getErrorStream(); 13660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson StringBuilder result = new StringBuilder(); 13670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson for (int i = 0; i < count; i++) { 13680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson int value = in.read(); 13690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson if (value == -1) { 13700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson in.close(); 13710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson break; 13720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson result.append((char) value); 13740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return result.toString(); 13760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private String readAscii(URLConnection connection) throws IOException { 13790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return readAscii(connection, Integer.MAX_VALUE); 13800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void reliableSkip(InputStream in, int length) throws IOException { 13830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson while (length > 0) { 13840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson length -= in.skip(length); 13850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1388953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson private void assertBadGateway(HttpURLConnection connection) throws IOException { 1389c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson try { 1390c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.getInputStream(); 1391c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson fail(); 1392c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } catch (FileNotFoundException expected) { 1393c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 1394953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals(HttpURLConnection.HTTP_BAD_GATEWAY, connection.getResponseCode()); 1395953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals(-1, connection.getErrorStream().read()); 1396c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 1397c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 13980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson enum TransferKind { 13990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson CHUNKED() { 14000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) 14010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson throws IOException { 14020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setChunkedBody(content, chunkSize); 14030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }, 14050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson FIXED_LENGTH() { 14060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) { 14070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setBody(content); 14080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }, 14100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson END_OF_STREAM() { 14110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) { 14120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setBody(content); 14130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setSocketPolicy(DISCONNECT_AT_END); 14140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson for (Iterator<String> h = response.getHeaders().iterator(); h.hasNext(); ) { 14150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson if (h.next().startsWith("Content-Length:")) { 14160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson h.remove(); 14170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson break; 14180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }; 14220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 14230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson abstract void setBody(MockResponse response, byte[] content, int chunkSize) 14240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson throws IOException; 14250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 14260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson void setBody(MockResponse response, String content, int chunkSize) throws IOException { 14270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson setBody(response, content.getBytes("UTF-8"), chunkSize); 14280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 14310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private <T> List<T> toListOrNull(T[] arrayOrNull) { 14320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return arrayOrNull != null ? Arrays.asList(arrayOrNull) : null; 14330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 14350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 14360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Returns a gzipped copy of {@code bytes}. 14370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 14380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public byte[] gzip(byte[] bytes) throws IOException { 14390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 14400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson OutputStream gzippedOut = new GZIPOutputStream(bytesOut); 14410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson gzippedOut.write(bytes); 14420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson gzippedOut.close(); 14430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return bytesOut.toByteArray(); 14440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1446433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson private class InsecureResponseCache extends ResponseCache { 14470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public CacheRequest put(URI uri, URLConnection connection) throws IOException { 1448433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson return cache.put(uri, connection); 14490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 14510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public CacheResponse get(URI uri, String requestMethod, 14520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson Map<String, List<String>> requestHeaders) throws IOException { 1453433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson final CacheResponse response = cache.get(uri, requestMethod, requestHeaders); 14540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson if (response instanceof SecureCacheResponse) { 14550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return new CacheResponse() { 14560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public InputStream getBody() throws IOException { 14570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return response.getBody(); 14580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public Map<String, List<String>> getHeaders() throws IOException { 14600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return response.getHeaders(); 14610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }; 14630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14640c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return response; 14650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson} 1468