HttpResponseCacheTest.java revision 396af46f45fd302e6309fc48ac1fd68cbb739edb
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 62396af46f45fd302e6309fc48ac1fd68cbb739edbJesse Wilsonpublic final class HttpResponseCacheTest extends TestCase { 630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private MockWebServer server = new MockWebServer(); 64396af46f45fd302e6309fc48ac1fd68cbb739edbJesse 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(); 72396af46f45fd302e6309fc48ac1fd68cbb739edbJesse 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(); 261ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getWriteSuccessCount()); 262ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(0, cache.getWriteAbortCount()); 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(); 273ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getWriteSuccessCount()); 274ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(0, cache.getWriteAbortCount()); 275ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(2, cache.getRequestCount()); 276ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getHitCount()); 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 303ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(2, cache.getRequestCount()); 304ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getNetworkCount()); 305ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getHitCount()); 3060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(suite, connection.getCipherSuite()); 3080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(localCerts, toListOrNull(connection.getLocalCertificates())); 3090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(serverCerts, toListOrNull(connection.getServerCertificates())); 3100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(peerPrincipal, connection.getPeerPrincipal()); 3110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(localPrincipal, connection.getLocalPrincipal()); 3120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 3130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testCacheReturnsInsecureResponseForSecureRequest() throws IOException { 3150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 3160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 3170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("ABC")); 3180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("DEF")); 3190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 3200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson ResponseCache.setDefault(new InsecureResponseCache()); 3220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 3240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 3250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 3260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // not cached! 3280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 3290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("DEF", readAscii(connection)); 3300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 3310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 332a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson public void testResponseCachingAndRedirects() throws Exception { 3330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 3340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 3370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Location: /foo")); 3380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 3390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setBody("ABC")); 3420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("DEF")); 3430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 3440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 345953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 3460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 3470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 348953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson connection = server.getUrl("/").openConnection(); // cached! 3490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 3500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 351ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(4, cache.getRequestCount()); // 2 requests + 2 redirects 352ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(2, cache.getNetworkCount()); 353ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(2, cache.getHitCount()); 3540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 3550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 356a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson public void testRedirectToCachedResult() throws Exception { 357a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson server.enqueue(new MockResponse() 358a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson .addHeader("Cache-Control: max-age=60") 359a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson .setBody("ABC")); 360a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson server.enqueue(new MockResponse() 361a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 362a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson .addHeader("Location: /foo")); 363a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson server.enqueue(new MockResponse().setBody("DEF")); 364a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson server.play(); 365a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson 366a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("ABC", readAscii(server.getUrl("/foo").openConnection())); 367a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson RecordedRequest request1 = server.takeRequest(); 368a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("GET /foo HTTP/1.1", request1.getRequestLine()); 369a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals(0, request1.getSequenceNumber()); 370a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson 371a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("ABC", readAscii(server.getUrl("/bar").openConnection())); 372a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson RecordedRequest request2 = server.takeRequest(); 373a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("GET /bar HTTP/1.1", request2.getRequestLine()); 374a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals(1, request2.getSequenceNumber()); 375a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson 376a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson // an unrelated request should reuse the pooled connection 377a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("DEF", readAscii(server.getUrl("/baz").openConnection())); 378a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson RecordedRequest request3 = server.takeRequest(); 379a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals("GET /baz HTTP/1.1", request3.getRequestLine()); 380a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson assertEquals(2, request3.getSequenceNumber()); 381a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson } 382a4193d7e636802a2705ffb52cb69c69ff59bfbb2Jesse Wilson 3830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testSecureResponseCachingAndRedirects() throws IOException { 3840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 3850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 3860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 3870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 3900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Location: /foo")); 3910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 3920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setBody("ABC")); 3950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("DEF")); 3960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 3970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 3980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 3990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 4000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 4010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached! 4030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 4040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABC", readAscii(connection)); 4050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 406ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4 407ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(2, cache.getHitCount()); 4080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testResponseCacheRequestHeaders() throws IOException, URISyntaxException { 4110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("ABC")); 4120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 4130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson final AtomicReference<Map<String, List<String>>> requestHeadersRef 4150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson = new AtomicReference<Map<String, List<String>>>(); 4160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson ResponseCache.setDefault(new ResponseCache() { 4170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public CacheResponse get(URI uri, String requestMethod, 4180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson Map<String, List<String>> requestHeaders) throws IOException { 4190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson requestHeadersRef.set(requestHeaders); 4200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return null; 4210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException { 4230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return null; 4240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }); 4260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 4280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URLConnection urlConnection = url.openConnection(); 4290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson urlConnection.addRequestProperty("A", "android"); 4300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson readAscii(urlConnection); 4310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals(Arrays.asList("android"), requestHeadersRef.get().get("A")); 4320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testServerDisconnectsPrematurelyWithContentLengthHeader() throws IOException { 4360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testServerPrematureDisconnect(TransferKind.FIXED_LENGTH); 4370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testServerDisconnectsPrematurelyWithChunkedEncoding() throws IOException { 4400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testServerPrematureDisconnect(TransferKind.CHUNKED); 4410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testServerDisconnectsPrematurelyWithNoLengthHeaders() throws IOException { 4440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /* 4450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Intentionally empty. This case doesn't make sense because there's no 4460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * such thing as a premature disconnect when the disconnect itself 4470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * indicates the end of the data stream. 4480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 4490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException { 4520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson MockResponse response = new MockResponse(); 4530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 16); 4540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(truncateViolently(response, 16)); 4550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("Request #2")); 4560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 4570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson BufferedReader reader = new BufferedReader(new InputStreamReader( 4590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.getUrl("/").openConnection().getInputStream())); 4600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABCDE", reader.readLine()); 4610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson try { 4620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson reader.readLine(); 4630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson fail("This implementation silently ignored a truncated HTTP body."); 4640c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } catch (IOException expected) { 465433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson } finally { 466433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson reader.close(); 4670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 469ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getWriteAbortCount()); 470ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(0, cache.getWriteSuccessCount()); 4710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 4720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("Request #2", readAscii(connection)); 473ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getWriteAbortCount()); 474ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getWriteSuccessCount()); 4750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testClientPrematureDisconnectWithContentLengthHeader() throws IOException { 4780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testClientPrematureDisconnect(TransferKind.FIXED_LENGTH); 4790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testClientPrematureDisconnectWithChunkedEncoding() throws IOException { 4820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testClientPrematureDisconnect(TransferKind.CHUNKED); 4830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testClientPrematureDisconnectWithNoLengthHeaders() throws IOException { 4860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testClientPrematureDisconnect(TransferKind.END_OF_STREAM); 4870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 4880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException { 4900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson MockResponse response = new MockResponse(); 4910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 1024); 4920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response); 4930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("Request #2")); 4940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 4950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 4960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 4970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson InputStream in = connection.getInputStream(); 4980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABCDE", readAscii(connection, 5)); 4990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson in.close(); 5000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson try { 5010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson in.read(); 5020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson fail("Expected an IOException because the stream is closed."); 5030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } catch (IOException expected) { 5040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 506ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getWriteAbortCount()); 507ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(0, cache.getWriteSuccessCount()); 5080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson connection = server.getUrl("/").openConnection(); 50984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("Request #2", readAscii(connection)); 510ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getWriteAbortCount()); 511ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getWriteSuccessCount()); 5120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 514953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson public void testDefaultExpirationDateFullyCachedForLessThan24Hours() throws Exception { 51521dddca4064527116af7a1553de502c6d11138daJesse Wilson // last modified: 105 seconds ago 51621dddca4064527116af7a1553de502c6d11138daJesse Wilson // served: 5 seconds ago 51721dddca4064527116af7a1553de502c6d11138daJesse Wilson // default lifetime: (105 - 5) / 10 = 10 seconds 51821dddca4064527116af7a1553de502c6d11138daJesse Wilson // expires: 10 seconds from served date = 5 seconds from now 519953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse() 52021dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS)) 521953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS)) 522953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .setBody("A")); 523953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.play(); 524953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 525953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URL url = server.getUrl("/"); 526953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 527953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = url.openConnection(); 528953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(connection)); 529953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertNull(connection.getHeaderField("Warning")); 53021dddca4064527116af7a1553de502c6d11138daJesse Wilson } 53121dddca4064527116af7a1553de502c6d11138daJesse Wilson 53221dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testDefaultExpirationDateConditionallyCached() throws Exception { 53321dddca4064527116af7a1553de502c6d11138daJesse Wilson // last modified: 115 seconds ago 53421dddca4064527116af7a1553de502c6d11138daJesse Wilson // served: 15 seconds ago 53521dddca4064527116af7a1553de502c6d11138daJesse Wilson // default lifetime: (115 - 15) / 10 = 10 seconds 53621dddca4064527116af7a1553de502c6d11138daJesse Wilson // expires: 10 seconds from served date = 5 seconds ago 53721dddca4064527116af7a1553de502c6d11138daJesse Wilson String lastModifiedDate = formatDate(-115, TimeUnit.SECONDS); 5380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 53921dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 54021dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Date: " + formatDate(-15, TimeUnit.SECONDS))); 5410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 5420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 5430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 545953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson public void testDefaultExpirationDateFullyCachedForMoreThan24Hours() throws Exception { 546953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson // last modified: 105 days ago 547953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson // served: 5 days ago 548953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson // default lifetime: (105 - 5) / 10 = 10 days 549953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson // expires: 10 days from served date = 5 days from now 550953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse() 551953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.DAYS)) 552953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Date: " + formatDate(-5, TimeUnit.DAYS)) 553953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .setBody("A")); 554953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.play(); 555953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 556953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 557953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 558953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(connection)); 559953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("113 HttpURLConnection \"Heuristic expiration\"", 560953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson connection.getHeaderField("Warning")); 561953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson } 562953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 56321dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testNoDefaultExpirationForUrlsWithQueryString() throws Exception { 56421dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(new MockResponse() 56521dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS)) 56621dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS)) 56721dddca4064527116af7a1553de502c6d11138daJesse Wilson .setBody("A")); 56821dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(new MockResponse().setBody("B")); 56921dddca4064527116af7a1553de502c6d11138daJesse Wilson server.play(); 57021dddca4064527116af7a1553de502c6d11138daJesse Wilson 57121dddca4064527116af7a1553de502c6d11138daJesse Wilson URL url = server.getUrl("/?foo=bar"); 57221dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("A", readAscii(url.openConnection())); 57321dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("B", readAscii(url.openConnection())); 57421dddca4064527116af7a1553de502c6d11138daJesse Wilson } 57521dddca4064527116af7a1553de502c6d11138daJesse Wilson 5760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testExpirationDateInThePastWithLastModifiedHeader() throws Exception { 5770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 5780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 5790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 5800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 5810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 5820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 5830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 5850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testExpirationDateInThePastWithNoLastModifiedHeader() throws Exception { 5860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse() 5870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 5880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 5900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testExpirationDateInTheFuture() throws Exception { 5910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertFullyCached(new MockResponse() 5920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 5930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 5940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 5950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testMaxAgePreferredWithMaxAgeAndExpires() throws Exception { 5960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertFullyCached(new MockResponse() 5970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.HOURS)) 5980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)) 5990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: max-age=60")); 6000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testMaxAgeInThePastWithDateAndLastModifiedHeaders() throws Exception { 6030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 6040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 6050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS)) 6060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 6070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: max-age=60")); 6080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 6090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 6100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testMaxAgeInThePastWithDateHeaderButNoLastModifiedHeader() throws Exception { 61384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson /* 61484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson * Chrome interprets max-age relative to the local clock. Both our cache 61584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson * and Firefox both use the earlier of the local and server's clock. 61684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson */ 6170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse() 6180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS)) 6190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: max-age=60")); 6200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testMaxAgeInTheFutureWithDateHeader() throws Exception { 6230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertFullyCached(new MockResponse() 6240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.HOURS)) 6250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: max-age=60")); 6260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testMaxAgeInTheFutureWithNoDateHeader() throws Exception { 6290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertFullyCached(new MockResponse() 6300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: max-age=60")); 6310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 633adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson public void testMaxAgeWithLastModifiedButNoServedDate() throws Exception { 634adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertFullyCached(new MockResponse() 635adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 636adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Cache-Control: max-age=60")); 637adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson } 638adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 639adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson public void testMaxAgeInTheFutureWithDateAndLastModifiedHeaders() throws Exception { 640adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertFullyCached(new MockResponse() 641adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 642adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 643adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Cache-Control: max-age=60")); 644adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson } 645adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 64621dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testMaxAgePreferredOverLowerSharedMaxAge() throws Exception { 64721dddca4064527116af7a1553de502c6d11138daJesse Wilson assertFullyCached(new MockResponse() 64821dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 64921dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: s-maxage=60") 65021dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: max-age=180")); 65121dddca4064527116af7a1553de502c6d11138daJesse Wilson } 65221dddca4064527116af7a1553de502c6d11138daJesse Wilson 65321dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testMaxAgePreferredOverHigherMaxAge() throws Exception { 65421dddca4064527116af7a1553de502c6d11138daJesse Wilson assertNotCached(new MockResponse() 65521dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 65621dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: s-maxage=180") 65721dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: max-age=60")); 65821dddca4064527116af7a1553de502c6d11138daJesse Wilson } 65921dddca4064527116af7a1553de502c6d11138daJesse Wilson 6600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodOptionsIsNotCached() throws Exception { 6610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("OPTIONS", false); 6620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6640c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodGetIsCached() throws Exception { 6650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("GET", true); 6660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodHeadIsNotCached() throws Exception { 6690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // We could support this but choose not to for implementation simplicity 6700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("HEAD", false); 6710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodPostIsNotCached() throws Exception { 6740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // We could support this but choose not to for implementation simplicity 6750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("POST", false); 6760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodPutIsNotCached() throws Exception { 6790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("PUT", false); 6800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodDeleteIsNotCached() throws Exception { 6830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("DELETE", false); 6840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testRequestMethodTraceIsNotCached() throws Exception { 6870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testRequestMethod("TRACE", false); 6880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 6890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 6900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void testRequestMethod(String requestMethod, boolean expectCached) throws Exception { 6910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /* 6920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 1. seed the cache (potentially) 6930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 2. expect a cache hit or miss 6940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 6950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 6960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 6970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("X-Response-ID: 1")); 6980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse() 6990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("X-Response-ID: 2")); 7000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 7010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 7030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpURLConnection request1 = (HttpURLConnection) url.openConnection(); 7050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson request1.setRequestMethod(requestMethod); 7060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson addRequestBodyIfNecessary(requestMethod, request1); 7070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("1", request1.getHeaderField("X-Response-ID")); 7080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 709953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection request2 = url.openConnection(); 7100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson if (expectCached) { 7110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("1", request1.getHeaderField("X-Response-ID")); 7120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } else { 7130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("2", request2.getHeaderField("X-Response-ID")); 7140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testPostInvalidatesCache() throws Exception { 7180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testMethodInvalidates("POST"); 7190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testPutInvalidatesCache() throws Exception { 7220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testMethodInvalidates("PUT"); 7230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testDeleteMethodInvalidatesCache() throws Exception { 7260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson testMethodInvalidates("DELETE"); 7270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void testMethodInvalidates(String requestMethod) throws Exception { 7300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /* 7310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 1. seed the cache 7320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 2. invalidate it 7330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 3. expect a cache miss 7340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 7350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("A") 7360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 7370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 7380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("C")); 7390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 7400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 7420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 7440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson HttpURLConnection invalidate = (HttpURLConnection) url.openConnection(); 7460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson invalidate.setRequestMethod(requestMethod); 7470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson addRequestBodyIfNecessary(requestMethod, invalidate); 7480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("B", readAscii(invalidate)); 7490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("C", readAscii(url.openConnection())); 7510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testEtag() throws Exception { 7540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 7550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("ETag: v1")); 7560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(conditionalRequest.getHeaders().contains("If-None-Match: v1")); 7570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testEtagAndExpirationDateInThePast() throws Exception { 7600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 7610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 7620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("ETag: v1") 7630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 7640c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 7650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 7660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-None-Match: v1")); 7670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 7680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testEtagAndExpirationDateInTheFuture() throws Exception { 7710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertFullyCached(new MockResponse() 7720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("ETag: v1") 7730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 7740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 7750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testCacheControlNoCache() throws Exception { 7780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse().addHeader("Cache-Control: no-cache")); 7790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testCacheControlNoCacheAndExpirationDateInTheFuture() throws Exception { 7820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 7830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 7840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 7850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 7860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: no-cache")); 7870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 7880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 7890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testPragmaNoCache() throws Exception { 7920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse().addHeader("Pragma: no-cache")); 7930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 7940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 7950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testPragmaNoCacheAndExpirationDateInTheFuture() throws Exception { 7960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 7970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 7980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 7990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 8000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Pragma: no-cache")); 8010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = conditionalRequest.getHeaders(); 8020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 8030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testCacheControlNoStore() throws Exception { 8060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse().addHeader("Cache-Control: no-store")); 8070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testCacheControlNoStoreAndExpirationDateInTheFuture() throws Exception { 8100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNotCached(new MockResponse() 8110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 8130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Cache-Control: no-store")); 8140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testPartialRangeResponsesDoNotCorruptCache() throws Exception { 8170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /* 8180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 1. request a range 8190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * 2. request a full document, expecting a cache miss 8200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 8210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("AA") 8220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setResponseCode(HttpURLConnection.HTTP_PARTIAL) 8230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 8240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Content-Range: bytes 1000-1001/2000")); 8250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("BB")); 8260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 8270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 8290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URLConnection range = url.openConnection(); 8310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson range.addRequestProperty("Range", "bytes=1000-1001"); 8320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("AA", readAscii(range)); 8330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("BB", readAscii(url.openConnection())); 8350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testServerReturnsDocumentOlderThanCache() throws Exception { 8380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("A") 8390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 8410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("B") 8420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-4, TimeUnit.HOURS))); 8430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 8440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 8460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 8480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 8490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testNonIdentityEncodingAndConditionalCache() throws Exception { 8520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNonIdentityEncodingCached(new MockResponse() 8530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 8550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testNonIdentityEncodingAndFullCache() throws Exception { 8580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertNonIdentityEncodingCached(new MockResponse() 8590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 8610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void assertNonIdentityEncodingCached(MockResponse response) throws Exception { 8640c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response 8650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .setBody(gzip("ABCABCABC".getBytes("UTF-8"))) 8660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Content-Encoding: gzip")); 8670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 8680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 8700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABCABCABC", readAscii(server.getUrl("/").openConnection())); 8710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("ABCABCABC", readAscii(server.getUrl("/").openConnection())); 8720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 8740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public void testExpiresDateBeforeModifiedDate() throws Exception { 8750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertConditionallyCached(new MockResponse() 8760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 8770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson .addHeader("Expires: " + formatDate(-2, TimeUnit.HOURS))); 8780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 8790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 880adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson public void testRequestMaxAge() throws IOException { 881adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.enqueue(new MockResponse().setBody("A") 882adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 883adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES)) 884adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 885adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 886adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 887adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.play(); 888adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 889adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 890adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 891adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson connection.addRequestProperty("Cache-Control", "max-age=30"); 892adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertEquals("B", readAscii(connection)); 893adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson } 894adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 895adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson public void testRequestMinFresh() throws IOException { 896adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.enqueue(new MockResponse().setBody("A") 897adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Cache-Control: max-age=60") 898adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 899adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 900adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 901adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson server.play(); 902adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 903adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 904adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 905adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson connection.addRequestProperty("Cache-Control", "min-fresh=120"); 906adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson assertEquals("B", readAscii(connection)); 907adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson } 908adb64fbba2b781467e055706c3de0873dfc01166Jesse Wilson 909c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson public void testRequestMaxStale() throws IOException { 910c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.enqueue(new MockResponse().setBody("A") 911c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Cache-Control: max-age=120") 912c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES))); 913c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.enqueue(new MockResponse().setBody("B")); 914c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 915c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.play(); 916c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 917c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 918c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 919c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.addRequestProperty("Cache-Control", "max-stale=180"); 920c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(connection)); 921953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("110 HttpURLConnection \"Response is stale\"", 922953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson connection.getHeaderField("Warning")); 923c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 924c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 9252f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson public void testRequestMaxStaleNotHonoredWithMustRevalidate() throws IOException { 9262f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.enqueue(new MockResponse().setBody("A") 9272f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson .addHeader("Cache-Control: max-age=120, must-revalidate") 9282f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES))); 9292f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 9302f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 9312f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.play(); 9322f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 9332f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 9342f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 9352f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson connection.addRequestProperty("Cache-Control", "max-stale=180"); 9362f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals("B", readAscii(connection)); 9372f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson } 9382f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 939c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson public void testRequestOnlyIfCachedWithNoResponseCached() throws IOException { 940c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson // (no responses enqueued) 941c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.play(); 942c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 943953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 944c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.addRequestProperty("Cache-Control", "only-if-cached"); 945c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertBadGateway(connection); 946c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 947c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 948c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson public void testRequestOnlyIfCachedWithFullResponseCached() throws IOException { 949c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.enqueue(new MockResponse().setBody("A") 950c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Cache-Control: max-age=30") 951c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 952c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.play(); 953c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 954c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 955c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 956c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.addRequestProperty("Cache-Control", "only-if-cached"); 957c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 958c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 959c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 960c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson public void testRequestOnlyIfCachedWithConditionalResponseCached() throws IOException { 961c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.enqueue(new MockResponse().setBody("A") 962c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Cache-Control: max-age=30") 963c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES))); 964c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.play(); 965c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 966c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 967953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 968c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.addRequestProperty("Cache-Control", "only-if-cached"); 969c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertBadGateway(connection); 970c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 971c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 972c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson public void testRequestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException { 973c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.enqueue(new MockResponse().setBody("A")); 974c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson server.play(); 975c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 976c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 977953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 978c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.addRequestProperty("Cache-Control", "only-if-cached"); 979c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson assertBadGateway(connection); 980c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 981c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 98284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testRequestCacheControlNoCache() throws Exception { 98384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse() 98484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 98584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 98684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Cache-Control: max-age=60") 98784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .setBody("A")); 98884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 98984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.play(); 99084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 99184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson URL url = server.getUrl("/"); 99284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 99384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson URLConnection connection = url.openConnection(); 99484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson connection.setRequestProperty("Cache-Control", "no-cache"); 99584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("B", readAscii(connection)); 99684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 99784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 99884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testRequestPragmaNoCache() throws Exception { 99984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse() 100084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 100184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 100284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Cache-Control: max-age=60") 100384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .setBody("A")); 100484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 100584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.play(); 100684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 100784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson URL url = server.getUrl("/"); 100884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 100984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson URLConnection connection = url.openConnection(); 101084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson connection.setRequestProperty("Pragma", "no-cache"); 101184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("B", readAscii(connection)); 101284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 101384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 101484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testClientSuppliedIfModifiedSinceWithCachedResult() throws Exception { 101584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson MockResponse response = new MockResponse() 101684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("ETag: v3") 101784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Cache-Control: max-age=0"); 101884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson String ifModifiedSinceDate = formatDate(-24, TimeUnit.HOURS); 101984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson RecordedRequest request = assertClientSuppliedCondition( 102084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson response, "If-Modified-Since", ifModifiedSinceDate); 102184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson List<String> headers = request.getHeaders(); 102284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertTrue(headers.contains("If-Modified-Since: " + ifModifiedSinceDate)); 102384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertFalse(headers.contains("If-None-Match: v3")); 102484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 102584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 102684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testClientSuppliedIfNoneMatchSinceWithCachedResult() throws Exception { 102784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson String lastModifiedDate = formatDate(-3, TimeUnit.MINUTES); 102884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson MockResponse response = new MockResponse() 102984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Last-Modified: " + lastModifiedDate) 103084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 103184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .addHeader("Cache-Control: max-age=0"); 103284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson RecordedRequest request = assertClientSuppliedCondition( 103384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson response, "If-None-Match", "v1"); 103484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson List<String> headers = request.getHeaders(); 103584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertTrue(headers.contains("If-None-Match: v1")); 103684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertFalse(headers.contains("If-Modified-Since: " + lastModifiedDate)); 103784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 103884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 103984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson private RecordedRequest assertClientSuppliedCondition(MockResponse seed, String conditionName, 104084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson String conditionValue) throws Exception { 104184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(seed.setBody("A")); 104284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 104384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.play(); 104484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 104584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson URL url = server.getUrl("/"); 104684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 104784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 104884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 104984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson connection.addRequestProperty(conditionName, conditionValue); 105084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode()); 105184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("", readAscii(connection)); 105284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 105384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.takeRequest(); // seed 105484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson return server.takeRequest(); 105584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 105684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 10579531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson public void testSetIfModifiedSince() throws Exception { 10589531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson Date since = new Date(); 10599531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson server.enqueue(new MockResponse().setBody("A")); 10609531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson server.play(); 10619531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson 10629531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson URL url = server.getUrl("/"); 10639531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson URLConnection connection = url.openConnection(); 10649531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson connection.setIfModifiedSince(since.getTime()); 10659531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson assertEquals("A", readAscii(connection)); 10669531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson RecordedRequest request = server.takeRequest(); 10679531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson assertTrue(request.getHeaders().contains("If-Modified-Since: " + formatDate(since))); 10689531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson } 10699531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson 107084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson public void testClientSuppliedConditionWithoutCachedResult() throws Exception { 107184f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.enqueue(new MockResponse() 107284f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 107384f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson server.play(); 107484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson 107584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 107684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson String clientIfModifiedSince = formatDate(-24, TimeUnit.HOURS); 107784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson connection.addRequestProperty("If-Modified-Since", clientIfModifiedSince); 107884f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode()); 107984f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson assertEquals("", readAscii(connection)); 108084f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson } 1081c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 108221dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testAuthorizationRequestHeaderPreventsCaching() throws Exception { 108321dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(new MockResponse() 108421dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.MINUTES)) 108521dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: max-age=60") 108621dddca4064527116af7a1553de502c6d11138daJesse Wilson .setBody("A")); 108721dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(new MockResponse().setBody("B")); 108821dddca4064527116af7a1553de502c6d11138daJesse Wilson server.play(); 108921dddca4064527116af7a1553de502c6d11138daJesse Wilson 109021dddca4064527116af7a1553de502c6d11138daJesse Wilson URL url = server.getUrl("/"); 1091953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = url.openConnection(); 109221dddca4064527116af7a1553de502c6d11138daJesse Wilson connection.addRequestProperty("Authorization", "password"); 109321dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("A", readAscii(connection)); 109421dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("B", readAscii(url.openConnection())); 109521dddca4064527116af7a1553de502c6d11138daJesse Wilson } 109621dddca4064527116af7a1553de502c6d11138daJesse Wilson 109721dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testAuthorizationResponseCachedWithSMaxAge() throws Exception { 109821dddca4064527116af7a1553de502c6d11138daJesse Wilson assertAuthorizationRequestFullyCached(new MockResponse() 109921dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: s-maxage=60")); 110021dddca4064527116af7a1553de502c6d11138daJesse Wilson } 110121dddca4064527116af7a1553de502c6d11138daJesse Wilson 110221dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testAuthorizationResponseCachedWithPublic() throws Exception { 110321dddca4064527116af7a1553de502c6d11138daJesse Wilson assertAuthorizationRequestFullyCached(new MockResponse() 110421dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: public")); 110521dddca4064527116af7a1553de502c6d11138daJesse Wilson } 110621dddca4064527116af7a1553de502c6d11138daJesse Wilson 110721dddca4064527116af7a1553de502c6d11138daJesse Wilson public void testAuthorizationResponseCachedWithMustRevalidate() throws Exception { 110821dddca4064527116af7a1553de502c6d11138daJesse Wilson assertAuthorizationRequestFullyCached(new MockResponse() 110921dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: must-revalidate")); 111021dddca4064527116af7a1553de502c6d11138daJesse Wilson } 111121dddca4064527116af7a1553de502c6d11138daJesse Wilson 111221dddca4064527116af7a1553de502c6d11138daJesse Wilson public void assertAuthorizationRequestFullyCached(MockResponse response) throws Exception { 111321dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(response 111421dddca4064527116af7a1553de502c6d11138daJesse Wilson .addHeader("Cache-Control: max-age=60") 111521dddca4064527116af7a1553de502c6d11138daJesse Wilson .setBody("A")); 111621dddca4064527116af7a1553de502c6d11138daJesse Wilson server.enqueue(new MockResponse().setBody("B")); 111721dddca4064527116af7a1553de502c6d11138daJesse Wilson server.play(); 111821dddca4064527116af7a1553de502c6d11138daJesse Wilson 111921dddca4064527116af7a1553de502c6d11138daJesse Wilson URL url = server.getUrl("/"); 1120953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection = url.openConnection(); 112121dddca4064527116af7a1553de502c6d11138daJesse Wilson connection.addRequestProperty("Authorization", "password"); 112221dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("A", readAscii(connection)); 112321dddca4064527116af7a1553de502c6d11138daJesse Wilson assertEquals("A", readAscii(url.openConnection())); 112421dddca4064527116af7a1553de502c6d11138daJesse Wilson } 112521dddca4064527116af7a1553de502c6d11138daJesse Wilson 1126953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson public void testVaryResponsesAreNotSupported() throws Exception { 1127953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse() 1128953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Cache-Control: max-age=60") 1129953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Vary: Accept-Language") 1130953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .setBody("A")); 1131953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 1132953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.play(); 1133953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 1134953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URL url = server.getUrl("/"); 1135953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection1 = url.openConnection(); 1136953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson connection1.addRequestProperty("Accept-Language", "fr-CA"); 1137953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(connection1)); 1138953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 1139953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson URLConnection connection2 = url.openConnection(); 1140953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson connection2.addRequestProperty("Accept-Language", "fr-CA"); 1141953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("B", readAscii(connection2)); 1142953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson } 1143953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 1144953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson public void testContentLocationDoesNotPopulateCache() throws Exception { 1145953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse() 1146953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Cache-Control: max-age=60") 1147953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .addHeader("Content-Location: /bar") 1148953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson .setBody("A")); 1149953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 1150953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson server.play(); 1151953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 1152953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("A", readAscii(server.getUrl("/foo").openConnection())); 1153953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals("B", readAscii(server.getUrl("/bar").openConnection())); 1154953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson } 1155953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson 115619c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson public void testUseCachesFalseDoesNotWriteToCache() throws Exception { 115719c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.enqueue(new MockResponse() 115819c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson .addHeader("Cache-Control: max-age=60") 115919c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson .setBody("A").setBody("A")); 116019c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 116119c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.play(); 116219c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson 116319c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 116419c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson connection.setUseCaches(false); 116519c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertEquals("A", readAscii(connection)); 116619c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertEquals("B", readAscii(server.getUrl("/").openConnection())); 116719c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson } 116819c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson 116919c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson public void testUseCachesFalseDoesNotReadFromCache() throws Exception { 117019c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.enqueue(new MockResponse() 117119c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson .addHeader("Cache-Control: max-age=60") 117219c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson .setBody("A").setBody("A")); 117319c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 117419c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson server.play(); 117519c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson 117619c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 117719c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 117819c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson connection.setUseCaches(false); 117919c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertEquals("B", readAscii(connection)); 118019c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson } 118119c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson 118219c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson public void testDefaultUseCachesSetsInitialValueOnly() throws Exception { 118319c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URL url = new URL("http://localhost/"); 118419c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URLConnection c1 = url.openConnection(); 118519c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URLConnection c2 = url.openConnection(); 118619c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertTrue(c1.getDefaultUseCaches()); 118719c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson c1.setDefaultUseCaches(false); 118819c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson try { 118919c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertTrue(c1.getUseCaches()); 119019c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertTrue(c2.getUseCaches()); 119119c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson URLConnection c3 = url.openConnection(); 119219c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson assertFalse(c3.getUseCaches()); 119319c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson } finally { 119419c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson c1.setDefaultUseCaches(true); 119519c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson } 119619c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson } 119719c77c6a6da8cea7327ccbb741963ac76d3fae53Jesse Wilson 11982f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson public void testConnectionIsReturnedToPoolAfterConditionalSuccess() throws Exception { 11992f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.enqueue(new MockResponse() 12002f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 12012f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson .addHeader("Cache-Control: max-age=0") 12022f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson .setBody("A")); 12032f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 12042f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 12052f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson server.play(); 12062f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 12072f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals("A", readAscii(server.getUrl("/a").openConnection())); 12082f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals("A", readAscii(server.getUrl("/a").openConnection())); 12092f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals("B", readAscii(server.getUrl("/b").openConnection())); 12102f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 12112f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals(0, server.takeRequest().getSequenceNumber()); 12122f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals(1, server.takeRequest().getSequenceNumber()); 12132f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson assertEquals(2, server.takeRequest().getSequenceNumber()); 12142f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson } 12152f16d502415452f808b5f077ad07b941645d14e4Jesse Wilson 1216757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson public void testStatisticsConditionalCacheMiss() throws Exception { 1217757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse() 1218757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1219757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .addHeader("Cache-Control: max-age=0") 1220757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .setBody("A")); 1221757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse().setBody("B")); 1222757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse().setBody("C")); 1223757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.play(); 1224757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 1225757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1226ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getRequestCount()); 1227ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getNetworkCount()); 1228ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(0, cache.getHitCount()); 1229757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("B", readAscii(server.getUrl("/").openConnection())); 1230757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("C", readAscii(server.getUrl("/").openConnection())); 1231ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(3, cache.getRequestCount()); 1232ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(3, cache.getNetworkCount()); 1233ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(0, cache.getHitCount()); 1234757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson } 1235757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 1236757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson public void testStatisticsConditionalCacheHit() throws Exception { 1237757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse() 1238757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1239757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .addHeader("Cache-Control: max-age=0") 1240757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .setBody("A")); 1241757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1242757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 1243757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.play(); 1244757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 1245757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1246ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getRequestCount()); 1247ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getNetworkCount()); 1248ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(0, cache.getHitCount()); 1249757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1250757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1251ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(3, cache.getRequestCount()); 1252ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(3, cache.getNetworkCount()); 1253ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(2, cache.getHitCount()); 1254757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson } 1255757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 1256757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson public void testStatisticsFullCacheHit() throws Exception { 1257757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.enqueue(new MockResponse() 1258757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .addHeader("Cache-Control: max-age=60") 1259757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson .setBody("A")); 1260757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson server.play(); 1261757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 1262757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1263ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getRequestCount()); 1264ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getNetworkCount()); 1265ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(0, cache.getHitCount()); 1266757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1267757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson assertEquals("A", readAscii(server.getUrl("/").openConnection())); 1268ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(3, cache.getRequestCount()); 1269ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(1, cache.getNetworkCount()); 1270ca8ae42fd6a787757897a680108bdcf7b0d37f13Jesse Wilson assertEquals(2, cache.getHitCount()); 1271757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson } 1272757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson 12730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 12740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * @param delta the offset from the current date to use. Negative 12750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * values yield dates in the past; positive values yield dates in the 12760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * future. 12770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 1278953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson private String formatDate(long delta, TimeUnit timeUnit) { 12799531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta))); 12809531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson } 12819531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson 12829531eea15052eccc004b5f853ab4452becf7a8abJesse Wilson private String formatDate(Date date) { 1283953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); 1284953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson rfc1123.setTimeZone(TimeZone.getTimeZone("UTC")); 1285953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson return rfc1123.format(date); 12860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 12870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 12880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void addRequestBodyIfNecessary(String requestMethod, HttpURLConnection invalidate) 12890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson throws IOException { 12900c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson if (requestMethod.equals("POST") || requestMethod.equals("PUT")) { 12910c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson invalidate.setDoOutput(true); 12920c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson OutputStream requestBody = invalidate.getOutputStream(); 12930c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson requestBody.write('x'); 12940c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson requestBody.close(); 12950c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 12960c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 12970c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 12980c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void assertNotCached(MockResponse response) throws Exception { 12990c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response.setBody("A")); 13000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("B")); 13010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 13020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 13040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 13050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("B", readAscii(url.openConnection())); 13060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 13090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * @return the request with the conditional get headers. 13100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 13110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private RecordedRequest assertConditionallyCached(MockResponse response) throws Exception { 13120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // scenario 1: condition succeeds 13130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response.setBody("A")); 13140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 13150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson // scenario 2: condition fails 13170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response.setBody("B")); 13180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(new MockResponse().setBody("C")); 13190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 13210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL valid = server.getUrl("/valid"); 13230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(valid.openConnection())); 13240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(valid.openConnection())); 13250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL invalid = server.getUrl("/invalid"); 13270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("B", readAscii(invalid.openConnection())); 13280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("C", readAscii(invalid.openConnection())); 13290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.takeRequest(); // regular get 13310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return server.takeRequest(); // conditional get 13320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void assertFullyCached(MockResponse response) throws Exception { 13350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response.setBody("A")); 13360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.enqueue(response.setBody("B")); 13370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson server.play(); 13380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson URL url = server.getUrl("/"); 13400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 13410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson assertEquals("A", readAscii(url.openConnection())); 13420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 13450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Shortens the body of {@code response} but not the corresponding headers. 13460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Only useful to test how clients respond to the premature conclusion of 13470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * the HTTP body. 13480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 13490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) { 13500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setSocketPolicy(DISCONNECT_AT_END); 13510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson List<String> headers = new ArrayList<String>(response.getHeaders()); 13520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setBody(Arrays.copyOfRange(response.getBody(), 0, numBytesToKeep)); 13530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.getHeaders().clear(); 13540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.getHeaders().addAll(headers); 13550c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return response; 13560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 13590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Reads {@code count} characters from the stream. If the stream is 13600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * exhausted before {@code count} characters can be read, the remaining 13610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * characters are returned and the stream is closed. 13620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 13630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private String readAscii(URLConnection connection, int count) throws IOException { 136484f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson HttpURLConnection httpConnection = (HttpURLConnection) connection; 136584f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson InputStream in = httpConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST 136684f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson ? connection.getInputStream() 136784f1fd18b9db6fc6f2bb65694bee99d42f88bb79Jesse Wilson : httpConnection.getErrorStream(); 13680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson StringBuilder result = new StringBuilder(); 13690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson for (int i = 0; i < count; i++) { 13700c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson int value = in.read(); 13710c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson if (value == -1) { 13720c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson in.close(); 13730c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson break; 13740c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13750c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson result.append((char) value); 13760c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13770c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return result.toString(); 13780c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13790c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13800c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private String readAscii(URLConnection connection) throws IOException { 13810c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return readAscii(connection, Integer.MAX_VALUE); 13820c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13830c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 13840c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private void reliableSkip(InputStream in, int length) throws IOException { 13850c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson while (length > 0) { 13860c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson length -= in.skip(length); 13870c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13880c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 13890c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1390953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson private void assertBadGateway(HttpURLConnection connection) throws IOException { 1391c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson try { 1392c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson connection.getInputStream(); 1393c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson fail(); 1394c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } catch (FileNotFoundException expected) { 1395c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 1396953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals(HttpURLConnection.HTTP_BAD_GATEWAY, connection.getResponseCode()); 1397953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson assertEquals(-1, connection.getErrorStream().read()); 1398c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson } 1399c9e12f729cb962eb60754e4500312421c46e71ddJesse Wilson 14000c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson enum TransferKind { 14010c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson CHUNKED() { 14020c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) 14030c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson throws IOException { 14040c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setChunkedBody(content, chunkSize); 14050c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14060c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }, 14070c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson FIXED_LENGTH() { 14080c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) { 14090c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setBody(content); 14100c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14110c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }, 14120c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson END_OF_STREAM() { 14130c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) { 14140c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setBody(content); 14150c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson response.setSocketPolicy(DISCONNECT_AT_END); 14160c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson for (Iterator<String> h = response.getHeaders().iterator(); h.hasNext(); ) { 14170c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson if (h.next().startsWith("Content-Length:")) { 14180c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson h.remove(); 14190c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson break; 14200c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14210c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14220c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14230c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }; 14240c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 14250c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson abstract void setBody(MockResponse response, byte[] content, int chunkSize) 14260c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson throws IOException; 14270c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 14280c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson void setBody(MockResponse response, String content, int chunkSize) throws IOException { 14290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson setBody(response, content.getBytes("UTF-8"), chunkSize); 14300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14310c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14320c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 14330c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private <T> List<T> toListOrNull(T[] arrayOrNull) { 14340c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return arrayOrNull != null ? Arrays.asList(arrayOrNull) : null; 14350c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14360c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 14370c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson /** 14380c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson * Returns a gzipped copy of {@code bytes}. 14390c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson */ 14400c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson public byte[] gzip(byte[] bytes) throws IOException { 14410c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 14420c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson OutputStream gzippedOut = new GZIPOutputStream(bytesOut); 14430c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson gzippedOut.write(bytes); 14440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson gzippedOut.close(); 14450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return bytesOut.toByteArray(); 14460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 1448433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson private class InsecureResponseCache extends ResponseCache { 14490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public CacheRequest put(URI uri, URLConnection connection) throws IOException { 1450433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson return cache.put(uri, connection); 14510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 14530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public CacheResponse get(URI uri, String requestMethod, 14540c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson Map<String, List<String>> requestHeaders) throws IOException { 1455433e3fac172d0c4449051b0c61c0c63b298a0903Jesse Wilson final CacheResponse response = cache.get(uri, requestMethod, requestHeaders); 14560c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson if (response instanceof SecureCacheResponse) { 14570c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return new CacheResponse() { 14580c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public InputStream getBody() throws IOException { 14590c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return response.getBody(); 14600c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14610c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public Map<String, List<String>> getHeaders() throws IOException { 14620c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return response.getHeaders(); 14630c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14640c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson }; 14650c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14660c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return response; 14670c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14680c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 14690c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson} 1470