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