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