mirror of
https://github.com/square/okhttp.git
synced 2025-12-25 00:01:02 +03:00
Merge pull request #874 from square/jw/response-source-header
Expose backwards-compatible response source header.
This commit is contained in:
@@ -78,6 +78,8 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
private int redirectionCount;
|
||||
protected IOException httpEngineFailure;
|
||||
protected HttpEngine httpEngine;
|
||||
/** Lazily created (with synthetic headers) on first call to getHeaders(). */
|
||||
private Headers responseHeaders;
|
||||
|
||||
/**
|
||||
* The most recently attempted route. This will be null if we haven't sent a
|
||||
@@ -133,13 +135,38 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
}
|
||||
}
|
||||
|
||||
private Headers getHeaders() throws IOException {
|
||||
if (responseHeaders == null) {
|
||||
Response response = getResponse().getResponse();
|
||||
Headers headers = response.headers();
|
||||
|
||||
responseHeaders = headers.newBuilder()
|
||||
.add(Platform.get().getPrefix() + "-Response-Source", responseSourceHeader(response))
|
||||
.build();
|
||||
}
|
||||
return responseHeaders;
|
||||
}
|
||||
|
||||
private static String responseSourceHeader(Response response) {
|
||||
if (response.networkResponse() == null) {
|
||||
if (response.cacheResponse() == null) {
|
||||
return "NONE";
|
||||
}
|
||||
return "CACHE " + response.code();
|
||||
}
|
||||
if (response.cacheResponse() == null) {
|
||||
return "NETWORK " + response.code();
|
||||
}
|
||||
return "CONDITIONAL_CACHE " + response.networkResponse().code();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the field at {@code position}. Returns null if there
|
||||
* are fewer than {@code position} headers.
|
||||
*/
|
||||
@Override public final String getHeaderField(int position) {
|
||||
try {
|
||||
return getResponse().getResponse().headers().value(position);
|
||||
return getHeaders().value(position);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -152,10 +179,9 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
*/
|
||||
@Override public final String getHeaderField(String fieldName) {
|
||||
try {
|
||||
Response response = getResponse().getResponse();
|
||||
return fieldName == null
|
||||
? StatusLine.get(response).toString()
|
||||
: response.headers().get(fieldName);
|
||||
? StatusLine.get(getResponse().getResponse()).toString()
|
||||
: getHeaders().get(fieldName);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -163,7 +189,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
|
||||
@Override public final String getHeaderFieldKey(int position) {
|
||||
try {
|
||||
return getResponse().getResponse().headers().name(position);
|
||||
return getHeaders().name(position);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -171,8 +197,8 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
|
||||
@Override public final Map<String, List<String>> getHeaderFields() {
|
||||
try {
|
||||
Response response = getResponse().getResponse();
|
||||
return OkHeaders.toMultimap(response.headers(), StatusLine.get(response).toString());
|
||||
return OkHeaders.toMultimap(getHeaders(),
|
||||
StatusLine.get(getResponse().getResponse()).toString());
|
||||
} catch (IOException e) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
package com.squareup.okhttp;
|
||||
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
import com.squareup.okhttp.mockwebserver.rule.MockWebServerRule;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
import static okio.Okio.buffer;
|
||||
import static okio.Okio.source;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class OkUrlFactoryTest {
|
||||
@Rule public MockWebServerRule serverRule = new MockWebServerRule();
|
||||
@Rule public TemporaryFolder cacheFolder = new TemporaryFolder();
|
||||
|
||||
private MockWebServer server;
|
||||
private OkUrlFactory factory;
|
||||
|
||||
@Before public void setUp() throws IOException {
|
||||
server = serverRule.get();
|
||||
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
client.setCache(new Cache(cacheFolder.getRoot(), 10 * 1024 * 1024));
|
||||
factory = new OkUrlFactory(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Response code 407 should only come from proxy servers. Android's client
|
||||
* throws if it is sent by an origin server.
|
||||
*/
|
||||
@Test public void originServerSends407() throws Exception {
|
||||
server.enqueue(new MockResponse().setResponseCode(407));
|
||||
|
||||
HttpURLConnection conn = factory.open(server.getUrl("/"));
|
||||
try {
|
||||
conn.getResponseCode();
|
||||
fail();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void networkResponseSourceHeader() throws Exception {
|
||||
server.enqueue(new MockResponse().setBody("Isla Sorna"));
|
||||
|
||||
HttpURLConnection connection = factory.open(server.getUrl("/"));
|
||||
assertResponseHeader(connection, "NETWORK 200");
|
||||
assertResponseBody(connection, "Isla Sorna");
|
||||
}
|
||||
|
||||
@Test public void networkFailureResponseSourceHeader() throws Exception {
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
|
||||
HttpURLConnection connection = factory.open(server.getUrl("/"));
|
||||
assertResponseHeader(connection, "NETWORK 404");
|
||||
}
|
||||
|
||||
@Test public void conditionalCacheHitResponseSourceHeaders() throws Exception {
|
||||
server.enqueue(new MockResponse()
|
||||
.addHeader("Last-Modified: " + formatDate(0, TimeUnit.SECONDS))
|
||||
.addHeader("Cache-Control: max-age=0")
|
||||
.setBody("Isla Nublar"));
|
||||
server.enqueue(new MockResponse().setResponseCode(304));
|
||||
|
||||
HttpURLConnection connection1 = factory.open(server.getUrl("/"));
|
||||
assertResponseHeader(connection1, "NETWORK 200");
|
||||
assertResponseBody(connection1, "Isla Nublar");
|
||||
|
||||
HttpURLConnection connection2 = factory.open(server.getUrl("/"));
|
||||
assertResponseHeader(connection2, "CONDITIONAL_CACHE 304");
|
||||
assertResponseBody(connection2, "Isla Nublar");
|
||||
}
|
||||
|
||||
@Test public void conditionalCacheMissResponseSourceHeaders() throws Exception {
|
||||
server.enqueue(new MockResponse()
|
||||
.addHeader("Last-Modified: " + formatDate(0, TimeUnit.SECONDS))
|
||||
.addHeader("Cache-Control: max-age=0")
|
||||
.setBody("Isla Nublar"));
|
||||
server.enqueue(new MockResponse().setBody("Isla Sorna"));
|
||||
|
||||
HttpURLConnection connection1 = factory.open(server.getUrl("/"));
|
||||
assertResponseHeader(connection1, "NETWORK 200");
|
||||
assertResponseBody(connection1, "Isla Nublar");
|
||||
|
||||
HttpURLConnection connection2 = factory.open(server.getUrl("/"));
|
||||
assertResponseHeader(connection2, "CONDITIONAL_CACHE 200");
|
||||
assertResponseBody(connection2, "Isla Sorna");
|
||||
}
|
||||
|
||||
@Test public void cacheResponseSourceHeaders() throws Exception {
|
||||
server.enqueue(new MockResponse()
|
||||
.addHeader("Expires: " + formatDate(2, TimeUnit.HOURS))
|
||||
.setBody("Isla Nublar"));
|
||||
|
||||
HttpURLConnection connection1 = factory.open(server.getUrl("/"));
|
||||
assertResponseHeader(connection1, "NETWORK 200");
|
||||
assertResponseBody(connection1, "Isla Nublar");
|
||||
|
||||
HttpURLConnection connection2 = factory.open(server.getUrl("/"));
|
||||
assertResponseHeader(connection2, "CACHE 200");
|
||||
assertResponseBody(connection2, "Isla Nublar");
|
||||
}
|
||||
|
||||
@Test public void noneResponseSourceHeaders() throws Exception {
|
||||
server.enqueue(new MockResponse().setBody("Isla Nublar"));
|
||||
|
||||
HttpURLConnection connection1 = factory.open(server.getUrl("/"));
|
||||
assertResponseHeader(connection1, "NETWORK 200");
|
||||
assertResponseBody(connection1, "Isla Nublar");
|
||||
|
||||
HttpURLConnection connection2 = factory.open(server.getUrl("/"));
|
||||
connection2.setRequestProperty("Cache-Control", "only-if-cached");
|
||||
assertResponseHeader(connection2, "NONE");
|
||||
}
|
||||
|
||||
private void assertResponseBody(HttpURLConnection connection, String expected) throws Exception {
|
||||
String actual = buffer(source(connection.getInputStream())).readString(US_ASCII);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
private void assertResponseHeader(HttpURLConnection connection, String expected) {
|
||||
assertEquals(expected, connection.getHeaderField("OkHttp-Response-Source"));
|
||||
}
|
||||
|
||||
private static String formatDate(long delta, TimeUnit timeUnit) {
|
||||
return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta)));
|
||||
}
|
||||
|
||||
private static String formatDate(Date date) {
|
||||
DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
|
||||
rfc1123.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
return rfc1123.format(date);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user