1e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpackage com.squareup.okhttp; 2e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 36c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.internal.http.OkHeaders; 4ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubakerimport com.squareup.okhttp.internal.Platform; 5ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubakerimport com.squareup.okhttp.internal.URLFilter; 6ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubakerimport com.squareup.okhttp.internal.io.FileSystem; 771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fullerimport com.squareup.okhttp.internal.io.InMemoryFileSystem; 8e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.mockwebserver.MockResponse; 9e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.mockwebserver.MockWebServer; 1071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fullerimport java.io.File; 11e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.IOException; 12e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.HttpURLConnection; 13ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubakerimport java.net.URL; 14e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.text.DateFormat; 15e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.text.SimpleDateFormat; 16e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.Date; 17e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.Locale; 18e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.TimeZone; 19e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.concurrent.TimeUnit; 206c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport okio.BufferedSource; 216c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport org.junit.After; 22e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.Before; 23e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.Rule; 24e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.Test; 25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 26e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static java.nio.charset.StandardCharsets.US_ASCII; 27e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static okio.Okio.buffer; 28e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static okio.Okio.source; 29e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertEquals; 30e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.fail; 31e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 32e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpublic class OkUrlFactoryTest { 3371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Rule public MockWebServer server = new MockWebServer(); 346c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer @Rule public InMemoryFileSystem fileSystem = new InMemoryFileSystem(); 35e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 36e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private OkUrlFactory factory; 376c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer private Cache cache; 38e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Before public void setUp() throws IOException { 40e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller OkHttpClient client = new OkHttpClient(); 416c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer cache = new Cache(new File("/cache/"), 10 * 1024 * 1024, fileSystem); 426c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer client.setCache(cache); 43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller factory = new OkUrlFactory(client); 44e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 45e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 466c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer @After public void tearDown() throws IOException { 476c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer cache.delete(); 486c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 496c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 50e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 51e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Response code 407 should only come from proxy servers. Android's client 52e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * throws if it is sent by an origin server. 53e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 54e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void originServerSends407() throws Exception { 55e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setResponseCode(407)); 56e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 57e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection conn = factory.open(server.getUrl("/")); 58e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller try { 59e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller conn.getResponseCode(); 60e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller fail(); 61e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } catch (IOException ignored) { 62e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 63e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 64e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 65e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void networkResponseSourceHeader() throws Exception { 66e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("Isla Sorna")); 67e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 68e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection = factory.open(server.getUrl("/")); 69e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseHeader(connection, "NETWORK 200"); 70e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseBody(connection, "Isla Sorna"); 71e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 72e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 73e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void networkFailureResponseSourceHeader() throws Exception { 74e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setResponseCode(404)); 75e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 76e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection = factory.open(server.getUrl("/")); 77e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseHeader(connection, "NETWORK 404"); 786c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getErrorStream().close(); 79e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 80e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 81e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void conditionalCacheHitResponseSourceHeaders() throws Exception { 82e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 83e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(0, TimeUnit.SECONDS)) 84e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 85e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("Isla Nublar")); 86e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setResponseCode(304)); 87e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 88e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection1 = factory.open(server.getUrl("/")); 89e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseHeader(connection1, "NETWORK 200"); 90e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseBody(connection1, "Isla Nublar"); 91e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 92e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection2 = factory.open(server.getUrl("/")); 93e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseHeader(connection2, "CONDITIONAL_CACHE 304"); 94e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseBody(connection2, "Isla Nublar"); 95e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 96e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 97e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void conditionalCacheMissResponseSourceHeaders() throws Exception { 98e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 99e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Last-Modified: " + formatDate(0, TimeUnit.SECONDS)) 100e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Cache-Control: max-age=0") 101e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("Isla Nublar")); 102e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("Isla Sorna")); 103e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 104e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection1 = factory.open(server.getUrl("/")); 105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseHeader(connection1, "NETWORK 200"); 106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseBody(connection1, "Isla Nublar"); 107e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 108e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection2 = factory.open(server.getUrl("/")); 109e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseHeader(connection2, "CONDITIONAL_CACHE 200"); 110e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseBody(connection2, "Isla Sorna"); 111e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 112e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 113e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void cacheResponseSourceHeaders() throws Exception { 114e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 115e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Expires: " + formatDate(2, TimeUnit.HOURS)) 116e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("Isla Nublar")); 117e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 118e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection1 = factory.open(server.getUrl("/")); 119e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseHeader(connection1, "NETWORK 200"); 120e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseBody(connection1, "Isla Nublar"); 121e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 122e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection2 = factory.open(server.getUrl("/")); 123e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseHeader(connection2, "CACHE 200"); 124e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseBody(connection2, "Isla Nublar"); 125e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 126e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 127e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void noneResponseSourceHeaders() throws Exception { 128e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("Isla Nublar")); 129e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 130e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection1 = factory.open(server.getUrl("/")); 131e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseHeader(connection1, "NETWORK 200"); 132e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseBody(connection1, "Isla Nublar"); 133e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 134e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection2 = factory.open(server.getUrl("/")); 135e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection2.setRequestProperty("Cache-Control", "only-if-cached"); 136e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseHeader(connection2, "NONE"); 137e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 138e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 139e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test 140e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public void setInstanceFollowRedirectsFalse() throws Exception { 141e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 142e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(302) 143e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Location: /b") 144e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("A")); 145e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 146e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("B")); 147e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 148e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection connection = factory.open(server.getUrl("/a")); 149e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection.setInstanceFollowRedirects(false); 150e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseBody(connection, "A"); 151e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertResponseCode(connection, 302); 152e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 153e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 154ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker @Test 155ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker public void testURLFilter() throws Exception { 156ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker server.enqueue(new MockResponse() 157ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker .setBody("B")); 158ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker final URL blockedURL = server.url("/a").url(); 159ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker factory.setUrlFilter(new URLFilter() { 160ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker @Override 161ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker public void checkURLPermitted(URL url) throws IOException { 162ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker if (blockedURL.equals(url)) { 163ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker throw new IOException("Blocked"); 164ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker } 165ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker } 166ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker }); 167ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker try { 168ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker HttpURLConnection connection = factory.open(server.url("/a").url()); 169ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker connection.getInputStream(); 170ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker fail("Connection was successful"); 171ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker } catch (IOException e) { 172ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker assertEquals("Blocked", e.getMessage()); 173ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker } 174ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker HttpURLConnection connection = factory.open(server.url("/b").url()); 175ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker assertResponseBody(connection, "B"); 176ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker } 177ef5fc4b73ae643fa290ff6a473ade29f7f6526f7Chad Brubaker 178e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void assertResponseBody(HttpURLConnection connection, String expected) throws Exception { 1796c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer BufferedSource source = buffer(source(connection.getInputStream())); 1806c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer String actual = source.readString(US_ASCII); 1816c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer source.close(); 182e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(expected, actual); 183e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 184e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 185e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void assertResponseHeader(HttpURLConnection connection, String expected) { 1866c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertEquals(expected, connection.getHeaderField(OkHeaders.RESPONSE_SOURCE)); 187e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 188e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 189e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void assertResponseCode(HttpURLConnection connection, int expected) throws IOException { 190e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(expected, connection.getResponseCode()); 191e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 192e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 193e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private static String formatDate(long delta, TimeUnit timeUnit) { 194e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta))); 195e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 196e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 197e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private static String formatDate(Date date) { 198e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); 199e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller rfc1123.setTimeZone(TimeZone.getTimeZone("GMT")); 200e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return rfc1123.format(date); 201e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 202e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller} 203