mirror of
https://github.com/square/okhttp.git
synced 2025-08-08 23:42:08 +03:00
Merge pull request #2544 from square/jwilson.0508.no_synthetic_headers
Promote sent and received timestamps to fields on Response.
This commit is contained in:
@@ -106,7 +106,7 @@ public final class JavaApiConverter {
|
|||||||
okResponseBuilder.networkResponse(networkResponse);
|
okResponseBuilder.networkResponse(networkResponse);
|
||||||
|
|
||||||
// Response headers
|
// Response headers
|
||||||
Headers okHeaders = extractOkResponseHeaders(httpUrlConnection);
|
Headers okHeaders = extractOkResponseHeaders(httpUrlConnection, okResponseBuilder);
|
||||||
okResponseBuilder.headers(okHeaders);
|
okResponseBuilder.headers(okHeaders);
|
||||||
|
|
||||||
// Response body
|
// Response body
|
||||||
@@ -230,7 +230,7 @@ public final class JavaApiConverter {
|
|||||||
okResponseBuilder.message(statusLine.message);
|
okResponseBuilder.message(statusLine.message);
|
||||||
|
|
||||||
// Response headers
|
// Response headers
|
||||||
Headers okHeaders = extractOkHeaders(javaResponse);
|
Headers okHeaders = extractOkHeaders(javaResponse, okResponseBuilder);
|
||||||
okResponseBuilder.headers(okHeaders);
|
okResponseBuilder.headers(okHeaders);
|
||||||
|
|
||||||
// Response body
|
// Response body
|
||||||
@@ -281,7 +281,7 @@ public final class JavaApiConverter {
|
|||||||
.method(requestMethod, placeholderBody);
|
.method(requestMethod, placeholderBody);
|
||||||
|
|
||||||
if (requestHeaders != null) {
|
if (requestHeaders != null) {
|
||||||
Headers headers = extractOkHeaders(requestHeaders);
|
Headers headers = extractOkHeaders(requestHeaders, null);
|
||||||
builder.headers(headers);
|
builder.headers(headers);
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
@@ -292,7 +292,7 @@ public final class JavaApiConverter {
|
|||||||
* from the supplied {@link Response}.
|
* from the supplied {@link Response}.
|
||||||
*/
|
*/
|
||||||
public static CacheResponse createJavaCacheResponse(final Response response) {
|
public static CacheResponse createJavaCacheResponse(final Response response) {
|
||||||
final Headers headers = response.headers();
|
final Headers headers = withSyntheticHeaders(response);
|
||||||
final ResponseBody body = response.body();
|
final ResponseBody body = response.body();
|
||||||
if (response.request().isHttps()) {
|
if (response.request().isHttps()) {
|
||||||
final Handshake handshake = response.handshake();
|
final Handshake handshake = response.handshake();
|
||||||
@@ -382,6 +382,10 @@ public final class JavaApiConverter {
|
|||||||
* {@link Response}.
|
* {@link Response}.
|
||||||
*/
|
*/
|
||||||
static HttpURLConnection createJavaUrlConnectionForCachePut(Response okResponse) {
|
static HttpURLConnection createJavaUrlConnectionForCachePut(Response okResponse) {
|
||||||
|
okResponse = okResponse.newBuilder()
|
||||||
|
.body(null)
|
||||||
|
.headers(withSyntheticHeaders(okResponse))
|
||||||
|
.build();
|
||||||
Request request = okResponse.request();
|
Request request = okResponse.request();
|
||||||
// Create an object of the correct class in case the ResponseCache uses instanceof.
|
// Create an object of the correct class in case the ResponseCache uses instanceof.
|
||||||
if (request.isHttps()) {
|
if (request.isHttps()) {
|
||||||
@@ -391,6 +395,13 @@ public final class JavaApiConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Headers withSyntheticHeaders(Response okResponse) {
|
||||||
|
return okResponse.headers().newBuilder()
|
||||||
|
.add(OkHeaders.SENT_MILLIS, Long.toString(okResponse.sentRequestAtMillis()))
|
||||||
|
.add(OkHeaders.RECEIVED_MILLIS, Long.toString(okResponse.receivedResponseAtMillis()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts an immutable request header map from the supplied {@link Headers}.
|
* Extracts an immutable request header map from the supplied {@link Headers}.
|
||||||
*/
|
*/
|
||||||
@@ -402,26 +413,30 @@ public final class JavaApiConverter {
|
|||||||
* Extracts OkHttp headers from the supplied {@link java.net.CacheResponse}. Only real headers are
|
* Extracts OkHttp headers from the supplied {@link java.net.CacheResponse}. Only real headers are
|
||||||
* extracted. See {@link #extractStatusLine(java.net.CacheResponse)}.
|
* extracted. See {@link #extractStatusLine(java.net.CacheResponse)}.
|
||||||
*/
|
*/
|
||||||
private static Headers extractOkHeaders(CacheResponse javaResponse) throws IOException {
|
private static Headers extractOkHeaders(
|
||||||
|
CacheResponse javaResponse, Response.Builder okResponseBuilder) throws IOException {
|
||||||
Map<String, List<String>> javaResponseHeaders = javaResponse.getHeaders();
|
Map<String, List<String>> javaResponseHeaders = javaResponse.getHeaders();
|
||||||
return extractOkHeaders(javaResponseHeaders);
|
return extractOkHeaders(javaResponseHeaders, okResponseBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts OkHttp headers from the supplied {@link java.net.HttpURLConnection}. Only real headers
|
* Extracts OkHttp headers from the supplied {@link java.net.HttpURLConnection}. Only real headers
|
||||||
* are extracted. See {@link #extractStatusLine(java.net.HttpURLConnection)}.
|
* are extracted. See {@link #extractStatusLine(java.net.HttpURLConnection)}.
|
||||||
*/
|
*/
|
||||||
private static Headers extractOkResponseHeaders(HttpURLConnection httpUrlConnection) {
|
private static Headers extractOkResponseHeaders(
|
||||||
|
HttpURLConnection httpUrlConnection, Response.Builder okResponseBuilder) {
|
||||||
Map<String, List<String>> javaResponseHeaders = httpUrlConnection.getHeaderFields();
|
Map<String, List<String>> javaResponseHeaders = httpUrlConnection.getHeaderFields();
|
||||||
return extractOkHeaders(javaResponseHeaders);
|
return extractOkHeaders(javaResponseHeaders, okResponseBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts OkHttp headers from the supplied {@link Map}. Only real headers are extracted. Any
|
* Extracts OkHttp headers from the supplied {@link Map}. Only real headers are extracted. Any
|
||||||
* entry (one with a {@code null} key) is discarded.
|
* entry (one with a {@code null} key) is discarded. Special internal headers used to track cache
|
||||||
|
* metadata are omitted from the result and added to {@code okResponseBuilder} instead.
|
||||||
*/
|
*/
|
||||||
// @VisibleForTesting
|
// @VisibleForTesting
|
||||||
static Headers extractOkHeaders(Map<String, List<String>> javaHeaders) {
|
static Headers extractOkHeaders(
|
||||||
|
Map<String, List<String>> javaHeaders, Response.Builder okResponseBuilder) {
|
||||||
Headers.Builder okHeadersBuilder = new Headers.Builder();
|
Headers.Builder okHeadersBuilder = new Headers.Builder();
|
||||||
for (Map.Entry<String, List<String>> javaHeader : javaHeaders.entrySet()) {
|
for (Map.Entry<String, List<String>> javaHeader : javaHeaders.entrySet()) {
|
||||||
String name = javaHeader.getKey();
|
String name = javaHeader.getKey();
|
||||||
@@ -432,6 +447,16 @@ public final class JavaApiConverter {
|
|||||||
// explicitly ignored because Headers.Builder does not support null keys.
|
// explicitly ignored because Headers.Builder does not support null keys.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (okResponseBuilder != null && javaHeader.getValue().size() == 1) {
|
||||||
|
if (name.equals(OkHeaders.SENT_MILLIS)) {
|
||||||
|
okResponseBuilder.sentRequestAtMillis(Long.valueOf(javaHeader.getValue().get(0)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (name.equals(OkHeaders.RECEIVED_MILLIS)) {
|
||||||
|
okResponseBuilder.receivedResponseAtMillis(Long.valueOf(javaHeader.getValue().get(0)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (String value : javaHeader.getValue()) {
|
for (String value : javaHeader.getValue()) {
|
||||||
Internal.instance.addLenient(okHeadersBuilder, name, value);
|
Internal.instance.addLenient(okHeadersBuilder, name, value);
|
||||||
}
|
}
|
||||||
|
@@ -597,7 +597,7 @@ public class JavaApiConverterTest {
|
|||||||
javaResponseHeaders.put("key1", Arrays.asList("value1_1", "value1_2"));
|
javaResponseHeaders.put("key1", Arrays.asList("value1_1", "value1_2"));
|
||||||
javaResponseHeaders.put("key2", Arrays.asList("value2"));
|
javaResponseHeaders.put("key2", Arrays.asList("value2"));
|
||||||
|
|
||||||
Headers okHeaders = JavaApiConverter.extractOkHeaders(javaResponseHeaders);
|
Headers okHeaders = JavaApiConverter.extractOkHeaders(javaResponseHeaders, null);
|
||||||
assertEquals(3, okHeaders.size()); // null entry should be stripped out
|
assertEquals(3, okHeaders.size()); // null entry should be stripped out
|
||||||
assertEquals(Arrays.asList("value1_1", "value1_2"), okHeaders.values("key1"));
|
assertEquals(Arrays.asList("value1_1", "value1_2"), okHeaders.values("key1"));
|
||||||
assertEquals(Arrays.asList("value2"), okHeaders.values("key2"));
|
assertEquals(Arrays.asList("value2"), okHeaders.values("key2"));
|
||||||
|
@@ -193,8 +193,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END GET")
|
.assertLogEqual("--> END GET")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
|
|
||||||
@@ -207,8 +205,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END GET")
|
.assertLogEqual("--> END GET")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
}
|
}
|
||||||
@@ -228,8 +224,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END POST")
|
.assertLogEqual("--> END POST")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
|
|
||||||
@@ -244,8 +238,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END POST")
|
.assertLogEqual("--> END POST")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
}
|
}
|
||||||
@@ -264,8 +256,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END POST")
|
.assertLogEqual("--> END POST")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
|
|
||||||
@@ -279,8 +269,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END POST")
|
.assertLogEqual("--> END POST")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
}
|
}
|
||||||
@@ -307,8 +295,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END POST")
|
.assertLogEqual("--> END POST")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
|
|
||||||
@@ -323,8 +309,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END POST")
|
.assertLogEqual("--> END POST")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
}
|
}
|
||||||
@@ -344,8 +328,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 6")
|
.assertLogEqual("Content-Length: 6")
|
||||||
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
|
|
||||||
@@ -359,8 +341,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 6")
|
.assertLogEqual("Content-Length: 6")
|
||||||
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
}
|
}
|
||||||
@@ -377,8 +357,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END GET")
|
.assertLogEqual("--> END GET")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP (0-byte body)")
|
.assertLogEqual("<-- END HTTP (0-byte body)")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
|
|
||||||
@@ -391,8 +369,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END GET")
|
.assertLogEqual("--> END GET")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP (0-byte body)")
|
.assertLogEqual("<-- END HTTP (0-byte body)")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
}
|
}
|
||||||
@@ -418,8 +394,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END GET")
|
.assertLogEqual("--> END GET")
|
||||||
.assertLogMatch("<-- " + code + " No Content " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- " + code + " No Content " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP (0-byte body)")
|
.assertLogEqual("<-- END HTTP (0-byte body)")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
|
|
||||||
@@ -432,8 +406,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END GET")
|
.assertLogEqual("--> END GET")
|
||||||
.assertLogMatch("<-- " + code + " No Content " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- " + code + " No Content " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP (0-byte body)")
|
.assertLogEqual("<-- END HTTP (0-byte body)")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
}
|
}
|
||||||
@@ -455,8 +427,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END POST (3-byte body)")
|
.assertLogEqual("--> END POST (3-byte body)")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP (0-byte body)")
|
.assertLogEqual("<-- END HTTP (0-byte body)")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
|
|
||||||
@@ -473,8 +443,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END POST (3-byte body)")
|
.assertLogEqual("--> END POST (3-byte body)")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 0")
|
.assertLogEqual("Content-Length: 0")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP (0-byte body)")
|
.assertLogEqual("<-- END HTTP (0-byte body)")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
}
|
}
|
||||||
@@ -494,8 +462,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 6")
|
.assertLogEqual("Content-Length: 6")
|
||||||
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("")
|
.assertLogEqual("")
|
||||||
.assertLogEqual("Hello!")
|
.assertLogEqual("Hello!")
|
||||||
.assertLogEqual("<-- END HTTP (6-byte body)")
|
.assertLogEqual("<-- END HTTP (6-byte body)")
|
||||||
@@ -511,8 +477,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 6")
|
.assertLogEqual("Content-Length: 6")
|
||||||
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("")
|
.assertLogEqual("")
|
||||||
.assertLogEqual("Hello!")
|
.assertLogEqual("Hello!")
|
||||||
.assertLogEqual("<-- END HTTP (6-byte body)")
|
.assertLogEqual("<-- END HTTP (6-byte body)")
|
||||||
@@ -534,8 +498,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Transfer-encoding: chunked")
|
.assertLogEqual("Transfer-encoding: chunked")
|
||||||
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("")
|
.assertLogEqual("")
|
||||||
.assertLogEqual("Hello!")
|
.assertLogEqual("Hello!")
|
||||||
.assertLogEqual("<-- END HTTP (6-byte body)")
|
.assertLogEqual("<-- END HTTP (6-byte body)")
|
||||||
@@ -551,8 +513,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Transfer-encoding: chunked")
|
.assertLogEqual("Transfer-encoding: chunked")
|
||||||
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("")
|
.assertLogEqual("")
|
||||||
.assertLogEqual("Hello!")
|
.assertLogEqual("Hello!")
|
||||||
.assertLogEqual("<-- END HTTP (6-byte body)")
|
.assertLogEqual("<-- END HTTP (6-byte body)")
|
||||||
@@ -581,8 +541,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("Content-Encoding: gzip")
|
.assertLogEqual("Content-Encoding: gzip")
|
||||||
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
||||||
.assertLogMatch("Content-Length: \\d+")
|
.assertLogMatch("Content-Length: \\d+")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("<-- END HTTP (encoded body omitted)")
|
.assertLogEqual("<-- END HTTP (encoded body omitted)")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
|
|
||||||
@@ -591,8 +549,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogEqual("--> END GET")
|
.assertLogEqual("--> END GET")
|
||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
.assertLogEqual("Content-Type: text/plain; charset=utf-8")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("")
|
.assertLogEqual("")
|
||||||
.assertLogEqual("Hello, Hello, Hello")
|
.assertLogEqual("Hello, Hello, Hello")
|
||||||
.assertLogEqual("<-- END HTTP (19-byte body)")
|
.assertLogEqual("<-- END HTTP (19-byte body)")
|
||||||
@@ -618,8 +574,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Type: text/html; charset=0")
|
.assertLogEqual("Content-Type: text/html; charset=0")
|
||||||
.assertLogMatch("Content-Length: \\d+")
|
.assertLogMatch("Content-Length: \\d+")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogMatch("")
|
.assertLogMatch("")
|
||||||
.assertLogEqual("Couldn't decode the response body; charset is likely malformed.")
|
.assertLogEqual("Couldn't decode the response body; charset is likely malformed.")
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
@@ -631,8 +585,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Type: text/html; charset=0")
|
.assertLogEqual("Content-Type: text/html; charset=0")
|
||||||
.assertLogMatch("Content-Length: \\d+")
|
.assertLogMatch("Content-Length: \\d+")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("")
|
.assertLogEqual("")
|
||||||
.assertLogEqual("Couldn't decode the response body; charset is likely malformed.")
|
.assertLogEqual("Couldn't decode the response body; charset is likely malformed.")
|
||||||
.assertLogEqual("<-- END HTTP")
|
.assertLogEqual("<-- END HTTP")
|
||||||
@@ -670,8 +622,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 9")
|
.assertLogEqual("Content-Length: 9")
|
||||||
.assertLogEqual("Content-Type: image/png; charset=utf-8")
|
.assertLogEqual("Content-Type: image/png; charset=utf-8")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("")
|
.assertLogEqual("")
|
||||||
.assertLogEqual("<-- END HTTP (binary 9-byte body omitted)")
|
.assertLogEqual("<-- END HTTP (binary 9-byte body omitted)")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
@@ -686,8 +636,6 @@ public final class HttpLoggingInterceptorTest {
|
|||||||
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
.assertLogMatch("<-- 200 OK " + url + " \\(\\d+ms\\)")
|
||||||
.assertLogEqual("Content-Length: 9")
|
.assertLogEqual("Content-Length: 9")
|
||||||
.assertLogEqual("Content-Type: image/png; charset=utf-8")
|
.assertLogEqual("Content-Type: image/png; charset=utf-8")
|
||||||
.assertLogMatch("OkHttp-Sent-Millis: \\d+")
|
|
||||||
.assertLogMatch("OkHttp-Received-Millis: \\d+")
|
|
||||||
.assertLogEqual("")
|
.assertLogEqual("")
|
||||||
.assertLogEqual("<-- END HTTP (binary 9-byte body omitted)")
|
.assertLogEqual("<-- END HTTP (binary 9-byte body omitted)")
|
||||||
.assertNoMoreLogs();
|
.assertNoMoreLogs();
|
||||||
|
@@ -113,13 +113,25 @@ public final class CallTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test public void get() throws Exception {
|
@Test public void get() throws Exception {
|
||||||
server.enqueue(new MockResponse().setBody("abc").addHeader("Content-Type: text/plain"));
|
server.enqueue(new MockResponse()
|
||||||
|
.setBody("abc")
|
||||||
|
.clearHeaders()
|
||||||
|
.addHeader("content-type: text/plain")
|
||||||
|
.addHeader("content-length", "3"));
|
||||||
|
|
||||||
executeSynchronously("/", "User-Agent", "SyncApiTest")
|
long sentAt = System.currentTimeMillis();
|
||||||
.assertCode(200)
|
RecordedResponse recordedResponse = executeSynchronously("/", "User-Agent", "SyncApiTest");
|
||||||
|
long receivedAt = System.currentTimeMillis();
|
||||||
|
|
||||||
|
recordedResponse.assertCode(200)
|
||||||
.assertSuccessful()
|
.assertSuccessful()
|
||||||
.assertHeader("Content-Type", "text/plain")
|
.assertHeaders(new Headers.Builder()
|
||||||
.assertBody("abc");
|
.add("content-type", "text/plain")
|
||||||
|
.add("content-length", "3")
|
||||||
|
.build())
|
||||||
|
.assertBody("abc")
|
||||||
|
.assertSentRequestAtMillis(sentAt, receivedAt)
|
||||||
|
.assertReceivedResponseAtMillis(sentAt, receivedAt);
|
||||||
|
|
||||||
RecordedRequest recordedRequest = server.takeRequest();
|
RecordedRequest recordedRequest = server.takeRequest();
|
||||||
assertEquals("GET", recordedRequest.getMethod());
|
assertEquals("GET", recordedRequest.getMethod());
|
||||||
@@ -1178,31 +1190,48 @@ public final class CallTest {
|
|||||||
|
|
||||||
// Store a response in the cache.
|
// Store a response in the cache.
|
||||||
HttpUrl url = server.url("/");
|
HttpUrl url = server.url("/");
|
||||||
|
long request1SentAt = System.currentTimeMillis();
|
||||||
executeSynchronously("/", "Accept-Language", "fr-CA", "Accept-Charset", "UTF-8")
|
executeSynchronously("/", "Accept-Language", "fr-CA", "Accept-Charset", "UTF-8")
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertBody("A");
|
.assertBody("A");
|
||||||
|
long request1ReceivedAt = System.currentTimeMillis();
|
||||||
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
||||||
|
|
||||||
// Hit that stored response. It's different, but Vary says it doesn't matter.
|
// Hit that stored response. It's different, but Vary says it doesn't matter.
|
||||||
|
Thread.sleep(10); // Make sure the timestamps are unique.
|
||||||
RecordedResponse cacheHit = executeSynchronously(
|
RecordedResponse cacheHit = executeSynchronously(
|
||||||
"/", "Accept-Language", "en-US", "Accept-Charset", "UTF-8");
|
"/", "Accept-Language", "en-US", "Accept-Charset", "UTF-8");
|
||||||
|
|
||||||
// Check the merged response. The request is the application's original request.
|
// Check the merged response. The request is the application's original request.
|
||||||
cacheHit.assertCode(200)
|
cacheHit.assertCode(200)
|
||||||
.assertBody("A")
|
.assertBody("A")
|
||||||
.assertHeader("ETag", "v1")
|
.assertHeaders(new Headers.Builder()
|
||||||
|
.add("ETag", "v1")
|
||||||
|
.add("Cache-Control", "max-age=60")
|
||||||
|
.add("Vary", "Accept-Charset")
|
||||||
|
.add("Content-Length", "1")
|
||||||
|
.build())
|
||||||
.assertRequestUrl(url)
|
.assertRequestUrl(url)
|
||||||
.assertRequestHeader("Accept-Language", "en-US")
|
.assertRequestHeader("Accept-Language", "en-US")
|
||||||
.assertRequestHeader("Accept-Charset", "UTF-8");
|
.assertRequestHeader("Accept-Charset", "UTF-8")
|
||||||
|
.assertSentRequestAtMillis(request1SentAt, request1ReceivedAt)
|
||||||
|
.assertReceivedResponseAtMillis(request1SentAt, request1ReceivedAt);
|
||||||
|
|
||||||
// Check the cached response. Its request contains only the saved Vary headers.
|
// Check the cached response. Its request contains only the saved Vary headers.
|
||||||
cacheHit.cacheResponse()
|
cacheHit.cacheResponse()
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertHeader("ETag", "v1")
|
.assertHeaders(new Headers.Builder()
|
||||||
|
.add("ETag", "v1")
|
||||||
|
.add("Cache-Control", "max-age=60")
|
||||||
|
.add("Vary", "Accept-Charset")
|
||||||
|
.add("Content-Length", "1")
|
||||||
|
.build())
|
||||||
.assertRequestMethod("GET")
|
.assertRequestMethod("GET")
|
||||||
.assertRequestUrl(url)
|
.assertRequestUrl(url)
|
||||||
.assertRequestHeader("Accept-Language")
|
.assertRequestHeader("Accept-Language")
|
||||||
.assertRequestHeader("Accept-Charset", "UTF-8");
|
.assertRequestHeader("Accept-Charset", "UTF-8")
|
||||||
|
.assertSentRequestAtMillis(request1SentAt, request1ReceivedAt)
|
||||||
|
.assertReceivedResponseAtMillis(request1SentAt, request1ReceivedAt);
|
||||||
|
|
||||||
cacheHit.assertNoNetworkResponse();
|
cacheHit.assertNoNetworkResponse();
|
||||||
}
|
}
|
||||||
@@ -1222,15 +1251,20 @@ public final class CallTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Store a response in the cache.
|
// Store a response in the cache.
|
||||||
|
long request1At = System.currentTimeMillis();
|
||||||
executeSynchronously("/", "Accept-Language", "fr-CA", "Accept-Charset", "UTF-8")
|
executeSynchronously("/", "Accept-Language", "fr-CA", "Accept-Charset", "UTF-8")
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertHeader("Donut", "a")
|
.assertHeader("Donut", "a")
|
||||||
.assertBody("A");
|
.assertBody("A");
|
||||||
|
long request1ReceivedAt = System.currentTimeMillis();
|
||||||
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
||||||
|
|
||||||
// Hit that stored response. It's different, but Vary says it doesn't matter.
|
// Hit that stored response. It's different, but Vary says it doesn't matter.
|
||||||
|
Thread.sleep(10); // Make sure the timestamps are unique.
|
||||||
|
long request2SentAt = System.currentTimeMillis();
|
||||||
RecordedResponse cacheHit = executeSynchronously(
|
RecordedResponse cacheHit = executeSynchronously(
|
||||||
"/", "Accept-Language", "en-US", "Accept-Charset", "UTF-8");
|
"/", "Accept-Language", "en-US", "Accept-Charset", "UTF-8");
|
||||||
|
long request2ReceivedAt = System.currentTimeMillis();
|
||||||
assertEquals("v1", server.takeRequest().getHeader("If-None-Match"));
|
assertEquals("v1", server.takeRequest().getHeader("If-None-Match"));
|
||||||
|
|
||||||
// Check the merged response. The request is the application's original request.
|
// Check the merged response. The request is the application's original request.
|
||||||
@@ -1240,7 +1274,9 @@ public final class CallTest {
|
|||||||
.assertRequestUrl(server.url("/"))
|
.assertRequestUrl(server.url("/"))
|
||||||
.assertRequestHeader("Accept-Language", "en-US")
|
.assertRequestHeader("Accept-Language", "en-US")
|
||||||
.assertRequestHeader("Accept-Charset", "UTF-8")
|
.assertRequestHeader("Accept-Charset", "UTF-8")
|
||||||
.assertRequestHeader("If-None-Match"); // No If-None-Match on the user's request.
|
.assertRequestHeader("If-None-Match") // No If-None-Match on the user's request.
|
||||||
|
.assertSentRequestAtMillis(request1At, request1ReceivedAt)
|
||||||
|
.assertReceivedResponseAtMillis(request1At, request1ReceivedAt);
|
||||||
|
|
||||||
// Check the cached response. Its request contains only the saved Vary headers.
|
// Check the cached response. Its request contains only the saved Vary headers.
|
||||||
cacheHit.cacheResponse()
|
cacheHit.cacheResponse()
|
||||||
@@ -1250,7 +1286,9 @@ public final class CallTest {
|
|||||||
.assertRequestUrl(server.url("/"))
|
.assertRequestUrl(server.url("/"))
|
||||||
.assertRequestHeader("Accept-Language") // No Vary on Accept-Language.
|
.assertRequestHeader("Accept-Language") // No Vary on Accept-Language.
|
||||||
.assertRequestHeader("Accept-Charset", "UTF-8") // Because of Vary on Accept-Charset.
|
.assertRequestHeader("Accept-Charset", "UTF-8") // Because of Vary on Accept-Charset.
|
||||||
.assertRequestHeader("If-None-Match"); // This wasn't present in the original request.
|
.assertRequestHeader("If-None-Match") // This wasn't present in the original request.
|
||||||
|
.assertSentRequestAtMillis(request1At, request1ReceivedAt)
|
||||||
|
.assertReceivedResponseAtMillis(request1At, request1ReceivedAt);
|
||||||
|
|
||||||
// Check the network response. It has the caller's request, plus some caching headers.
|
// Check the network response. It has the caller's request, plus some caching headers.
|
||||||
cacheHit.networkResponse()
|
cacheHit.networkResponse()
|
||||||
@@ -1258,7 +1296,9 @@ public final class CallTest {
|
|||||||
.assertHeader("Donut", "b")
|
.assertHeader("Donut", "b")
|
||||||
.assertRequestHeader("Accept-Language", "en-US")
|
.assertRequestHeader("Accept-Language", "en-US")
|
||||||
.assertRequestHeader("Accept-Charset", "UTF-8")
|
.assertRequestHeader("Accept-Charset", "UTF-8")
|
||||||
.assertRequestHeader("If-None-Match", "v1"); // If-None-Match in the validation request.
|
.assertRequestHeader("If-None-Match", "v1") // If-None-Match in the validation request.
|
||||||
|
.assertSentRequestAtMillis(request2SentAt, request2ReceivedAt)
|
||||||
|
.assertReceivedResponseAtMillis(request2SentAt, request2ReceivedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void conditionalCacheHit_Async() throws Exception {
|
@Test public void conditionalCacheHit_Async() throws Exception {
|
||||||
@@ -1300,35 +1340,46 @@ public final class CallTest {
|
|||||||
.cache(cache)
|
.cache(cache)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
long request1SentAt = System.currentTimeMillis();
|
||||||
executeSynchronously("/", "Accept-Language", "fr-CA", "Accept-Charset", "UTF-8")
|
executeSynchronously("/", "Accept-Language", "fr-CA", "Accept-Charset", "UTF-8")
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertBody("A");
|
.assertBody("A");
|
||||||
|
long request1ReceivedAt = System.currentTimeMillis();
|
||||||
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
||||||
|
|
||||||
// Different request, but Vary says it doesn't matter.
|
// Different request, but Vary says it doesn't matter.
|
||||||
RecordedResponse cacheHit = executeSynchronously(
|
Thread.sleep(10); // Make sure the timestamps are unique.
|
||||||
|
long request2SentAt = System.currentTimeMillis();
|
||||||
|
RecordedResponse cacheMiss = executeSynchronously(
|
||||||
"/", "Accept-Language", "en-US", "Accept-Charset", "UTF-8");
|
"/", "Accept-Language", "en-US", "Accept-Charset", "UTF-8");
|
||||||
|
long request2ReceivedAt = System.currentTimeMillis();
|
||||||
assertEquals("v1", server.takeRequest().getHeader("If-None-Match"));
|
assertEquals("v1", server.takeRequest().getHeader("If-None-Match"));
|
||||||
|
|
||||||
// Check the user response. It has the application's original request.
|
// Check the user response. It has the application's original request.
|
||||||
cacheHit.assertCode(200)
|
cacheMiss.assertCode(200)
|
||||||
.assertBody("B")
|
.assertBody("B")
|
||||||
.assertHeader("Donut", "b")
|
.assertHeader("Donut", "b")
|
||||||
.assertRequestUrl(server.url("/"));
|
.assertRequestUrl(server.url("/"))
|
||||||
|
.assertSentRequestAtMillis(request2SentAt, request2ReceivedAt)
|
||||||
|
.assertReceivedResponseAtMillis(request2SentAt, request2ReceivedAt);
|
||||||
|
|
||||||
// Check the cache response. Even though it's a miss, we used the cache.
|
// Check the cache response. Even though it's a miss, we used the cache.
|
||||||
cacheHit.cacheResponse()
|
cacheMiss.cacheResponse()
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertHeader("Donut", "a")
|
.assertHeader("Donut", "a")
|
||||||
.assertHeader("ETag", "v1")
|
.assertHeader("ETag", "v1")
|
||||||
.assertRequestUrl(server.url("/"));
|
.assertRequestUrl(server.url("/"))
|
||||||
|
.assertSentRequestAtMillis(request1SentAt, request1ReceivedAt)
|
||||||
|
.assertReceivedResponseAtMillis(request1SentAt, request1ReceivedAt);
|
||||||
|
|
||||||
// Check the network response. It has the network request, plus caching headers.
|
// Check the network response. It has the network request, plus caching headers.
|
||||||
cacheHit.networkResponse()
|
cacheMiss.networkResponse()
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertHeader("Donut", "b")
|
.assertHeader("Donut", "b")
|
||||||
.assertRequestHeader("If-None-Match", "v1") // If-None-Match in the validation request.
|
.assertRequestHeader("If-None-Match", "v1") // If-None-Match in the validation request.
|
||||||
.assertRequestUrl(server.url("/"));
|
.assertRequestUrl(server.url("/"))
|
||||||
|
.assertSentRequestAtMillis(request2SentAt, request2ReceivedAt)
|
||||||
|
.assertReceivedResponseAtMillis(request2SentAt, request2ReceivedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void conditionalCacheMiss_Async() throws Exception {
|
@Test public void conditionalCacheMiss_Async() throws Exception {
|
||||||
|
@@ -16,7 +16,9 @@
|
|||||||
package okhttp3;
|
package okhttp3;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
import okhttp3.ws.WebSocket;
|
import okhttp3.ws.WebSocket;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -79,6 +81,11 @@ public final class RecordedResponse {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RecordedResponse assertHeaders(Headers headers) {
|
||||||
|
assertEquals(headers, response.headers());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public RecordedResponse assertBody(String expectedBody) {
|
public RecordedResponse assertBody(String expectedBody) {
|
||||||
assertEquals(expectedBody, body);
|
assertEquals(expectedBody, body);
|
||||||
return this;
|
return this;
|
||||||
@@ -147,4 +154,23 @@ public final class RecordedResponse {
|
|||||||
assertTrue(failure.getMessage(), Arrays.asList(messages).contains(failure.getMessage()));
|
assertTrue(failure.getMessage(), Arrays.asList(messages).contains(failure.getMessage()));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RecordedResponse assertSentRequestAtMillis(long minimum, long maximum) {
|
||||||
|
assertDateInRange(minimum, response.sentRequestAtMillis(), maximum);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecordedResponse assertReceivedResponseAtMillis(long minimum, long maximum) {
|
||||||
|
assertDateInRange(minimum, response.receivedResponseAtMillis(), maximum);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertDateInRange(long minimum, long actual, long maximum) {
|
||||||
|
assertTrue("actual " + format(actual) + " < minimum " + format(maximum), actual >= minimum);
|
||||||
|
assertTrue("actual " + format(actual) + " > maximum " + format(minimum), actual <= maximum);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String format(long time) {
|
||||||
|
return new SimpleDateFormat("HH:mm:ss.SSS").format(new Date(time));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,9 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import static okhttp3.TestUtil.headerEntries;
|
import static okhttp3.TestUtil.headerEntries;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
public final class HeadersTest {
|
public final class HeadersTest {
|
||||||
@@ -303,6 +305,16 @@ public final class HeadersTest {
|
|||||||
assertEquals(1, headerMap.get("user-agent").size());
|
assertEquals(1, headerMap.get("user-agent").size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void toMultimapUsesCanonicalCase() {
|
||||||
|
Headers headers = Headers.of(
|
||||||
|
"cache-control", "no-store",
|
||||||
|
"Cache-Control", "no-cache",
|
||||||
|
"User-Agent", "OkHttp");
|
||||||
|
Map<String, List<String>> headerMap = headers.toMultimap();
|
||||||
|
assertEquals(2, headerMap.get("cache-control").size());
|
||||||
|
assertEquals(1, headerMap.get("user-agent").size());
|
||||||
|
}
|
||||||
|
|
||||||
@Test public void nameIndexesAreStrict() {
|
@Test public void nameIndexesAreStrict() {
|
||||||
Headers headers = Headers.of("a", "b", "c", "d");
|
Headers headers = Headers.of("a", "b", "c", "d");
|
||||||
try {
|
try {
|
||||||
@@ -354,4 +366,30 @@ public final class HeadersTest {
|
|||||||
expected.getMessage());
|
expected.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void headersEquals() {
|
||||||
|
Headers headers1 = new Headers.Builder()
|
||||||
|
.add("Connection", "close")
|
||||||
|
.add("Transfer-Encoding", "chunked")
|
||||||
|
.build();
|
||||||
|
Headers headers2 = new Headers.Builder()
|
||||||
|
.add("Connection", "close")
|
||||||
|
.add("Transfer-Encoding", "chunked")
|
||||||
|
.build();
|
||||||
|
assertTrue(headers1.equals(headers2));
|
||||||
|
assertEquals(headers1.hashCode(), headers2.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void headersNotEquals() {
|
||||||
|
Headers headers1 = new Headers.Builder()
|
||||||
|
.add("Connection", "close")
|
||||||
|
.add("Transfer-Encoding", "chunked")
|
||||||
|
.build();
|
||||||
|
Headers headers2 = new Headers.Builder()
|
||||||
|
.add("Connection", "keep-alive")
|
||||||
|
.add("Transfer-Encoding", "chunked")
|
||||||
|
.build();
|
||||||
|
assertFalse(headers1.equals(headers2));
|
||||||
|
assertFalse(headers1.hashCode() == headers2.hashCode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -125,35 +125,25 @@ public final class URLEncodingTest {
|
|||||||
|
|
||||||
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||||
Internal.instance.setCache(builder, new InternalCache() {
|
Internal.instance.setCache(builder, new InternalCache() {
|
||||||
@Override
|
@Override public Response get(Request request) throws IOException {
|
||||||
public Response get(Request request) throws IOException {
|
|
||||||
uriReference.set(request.url().uri());
|
uriReference.set(request.url().uri());
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public CacheRequest put(Response response) throws IOException {
|
||||||
public CacheRequest put(Response response) throws IOException {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public void remove(Request request) throws IOException {
|
||||||
public void remove(Request request) throws IOException {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public void update(Response cached, Response network) throws IOException {
|
||||||
public void update(Response cached, Response network) throws IOException {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public void trackConditionalCacheHit() {
|
||||||
public void trackConditionalCacheHit() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public void trackResponse(CacheStrategy cacheStrategy) {
|
||||||
public void trackResponse(CacheStrategy cacheStrategy) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -478,6 +478,8 @@ public final class Cache implements Closeable, Flushable {
|
|||||||
private final String message;
|
private final String message;
|
||||||
private final Headers responseHeaders;
|
private final Headers responseHeaders;
|
||||||
private final Handshake handshake;
|
private final Handshake handshake;
|
||||||
|
private final long sentRequestMillis;
|
||||||
|
private final long receivedResponseMillis;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads an entry from an input stream. A typical entry looks like this:
|
* Reads an entry from an input stream. A typical entry looks like this:
|
||||||
@@ -548,6 +550,16 @@ public final class Cache implements Closeable, Flushable {
|
|||||||
for (int i = 0; i < responseHeaderLineCount; i++) {
|
for (int i = 0; i < responseHeaderLineCount; i++) {
|
||||||
responseHeadersBuilder.addLenient(source.readUtf8LineStrict());
|
responseHeadersBuilder.addLenient(source.readUtf8LineStrict());
|
||||||
}
|
}
|
||||||
|
String sendRequestMillisString = responseHeadersBuilder.get(OkHeaders.SENT_MILLIS);
|
||||||
|
String receivedResponseMillisString = responseHeadersBuilder.get(OkHeaders.RECEIVED_MILLIS);
|
||||||
|
responseHeadersBuilder.removeAll(OkHeaders.SENT_MILLIS);
|
||||||
|
responseHeadersBuilder.removeAll(OkHeaders.RECEIVED_MILLIS);
|
||||||
|
sentRequestMillis = sendRequestMillisString != null
|
||||||
|
? Long.parseLong(sendRequestMillisString)
|
||||||
|
: 0L;
|
||||||
|
receivedResponseMillis = receivedResponseMillisString != null
|
||||||
|
? Long.parseLong(receivedResponseMillisString)
|
||||||
|
: 0L;
|
||||||
responseHeaders = responseHeadersBuilder.build();
|
responseHeaders = responseHeadersBuilder.build();
|
||||||
|
|
||||||
if (isHttps()) {
|
if (isHttps()) {
|
||||||
@@ -580,45 +592,55 @@ public final class Cache implements Closeable, Flushable {
|
|||||||
this.message = response.message();
|
this.message = response.message();
|
||||||
this.responseHeaders = response.headers();
|
this.responseHeaders = response.headers();
|
||||||
this.handshake = response.handshake();
|
this.handshake = response.handshake();
|
||||||
|
this.sentRequestMillis = response.sentRequestAtMillis();
|
||||||
|
this.receivedResponseMillis = response.receivedResponseAtMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(DiskLruCache.Editor editor) throws IOException {
|
public void writeTo(DiskLruCache.Editor editor) throws IOException {
|
||||||
BufferedSink sink = Okio.buffer(editor.newSink(ENTRY_METADATA));
|
BufferedSink sink = Okio.buffer(editor.newSink(ENTRY_METADATA));
|
||||||
|
|
||||||
sink.writeUtf8(url);
|
sink.writeUtf8(url)
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
sink.writeUtf8(requestMethod);
|
sink.writeUtf8(requestMethod)
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
sink.writeDecimalLong(varyHeaders.size());
|
sink.writeDecimalLong(varyHeaders.size())
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
for (int i = 0, size = varyHeaders.size(); i < size; i++) {
|
for (int i = 0, size = varyHeaders.size(); i < size; i++) {
|
||||||
sink.writeUtf8(varyHeaders.name(i));
|
sink.writeUtf8(varyHeaders.name(i))
|
||||||
sink.writeUtf8(": ");
|
.writeUtf8(": ")
|
||||||
sink.writeUtf8(varyHeaders.value(i));
|
.writeUtf8(varyHeaders.value(i))
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
sink.writeUtf8(new StatusLine(protocol, code, message).toString());
|
sink.writeUtf8(new StatusLine(protocol, code, message).toString())
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
sink.writeDecimalLong(responseHeaders.size());
|
sink.writeDecimalLong(responseHeaders.size() + 2)
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
|
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
|
||||||
sink.writeUtf8(responseHeaders.name(i));
|
sink.writeUtf8(responseHeaders.name(i))
|
||||||
sink.writeUtf8(": ");
|
.writeUtf8(": ")
|
||||||
sink.writeUtf8(responseHeaders.value(i));
|
.writeUtf8(responseHeaders.value(i))
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
}
|
}
|
||||||
|
sink.writeUtf8(OkHeaders.SENT_MILLIS)
|
||||||
|
.writeUtf8(": ")
|
||||||
|
.writeDecimalLong(sentRequestMillis)
|
||||||
|
.writeByte('\n');
|
||||||
|
sink.writeUtf8(OkHeaders.RECEIVED_MILLIS)
|
||||||
|
.writeUtf8(": ")
|
||||||
|
.writeDecimalLong(receivedResponseMillis)
|
||||||
|
.writeByte('\n');
|
||||||
|
|
||||||
if (isHttps()) {
|
if (isHttps()) {
|
||||||
sink.writeByte('\n');
|
sink.writeByte('\n');
|
||||||
sink.writeUtf8(handshake.cipherSuite().javaName());
|
sink.writeUtf8(handshake.cipherSuite().javaName())
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
writeCertList(sink, handshake.peerCertificates());
|
writeCertList(sink, handshake.peerCertificates());
|
||||||
writeCertList(sink, handshake.localCertificates());
|
writeCertList(sink, handshake.localCertificates());
|
||||||
// The handshake’s TLS version is null on HttpsURLConnection and on older cached responses.
|
// The handshake’s TLS version is null on HttpsURLConnection and on older cached responses.
|
||||||
if (handshake.tlsVersion() != null) {
|
if (handshake.tlsVersion() != null) {
|
||||||
sink.writeUtf8(handshake.tlsVersion().javaName());
|
sink.writeUtf8(handshake.tlsVersion().javaName())
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sink.close();
|
sink.close();
|
||||||
@@ -650,13 +672,13 @@ public final class Cache implements Closeable, Flushable {
|
|||||||
private void writeCertList(BufferedSink sink, List<Certificate> certificates)
|
private void writeCertList(BufferedSink sink, List<Certificate> certificates)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
try {
|
try {
|
||||||
sink.writeDecimalLong(certificates.size());
|
sink.writeDecimalLong(certificates.size())
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
for (int i = 0, size = certificates.size(); i < size; i++) {
|
for (int i = 0, size = certificates.size(); i < size; i++) {
|
||||||
byte[] bytes = certificates.get(i).getEncoded();
|
byte[] bytes = certificates.get(i).getEncoded();
|
||||||
String line = ByteString.of(bytes).base64();
|
String line = ByteString.of(bytes).base64();
|
||||||
sink.writeUtf8(line);
|
sink.writeUtf8(line)
|
||||||
sink.writeByte('\n');
|
.writeByte('\n');
|
||||||
}
|
}
|
||||||
} catch (CertificateEncodingException e) {
|
} catch (CertificateEncodingException e) {
|
||||||
throw new IOException(e.getMessage());
|
throw new IOException(e.getMessage());
|
||||||
@@ -685,6 +707,8 @@ public final class Cache implements Closeable, Flushable {
|
|||||||
.headers(responseHeaders)
|
.headers(responseHeaders)
|
||||||
.body(new CacheResponseBody(snapshot, contentType, contentLength))
|
.body(new CacheResponseBody(snapshot, contentType, contentLength))
|
||||||
.handshake(handshake)
|
.handshake(handshake)
|
||||||
|
.sentRequestAtMillis(sentRequestMillis)
|
||||||
|
.receivedResponseAtMillis(receivedResponseMillis)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,10 +18,12 @@
|
|||||||
package okhttp3;
|
package okhttp3;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
@@ -113,6 +115,41 @@ public final class Headers {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if {@code other} is a {@code Headers} object with the same headers, with the same
|
||||||
|
* casing, in the same order. Note that two headers instances may be <i>semantically</i> equal
|
||||||
|
* but not equal according to this method. In particular, none of the following sets of headers
|
||||||
|
* are equal according to this method: <pre> {@code
|
||||||
|
*
|
||||||
|
* 1. Original
|
||||||
|
* Content-Type: text/html
|
||||||
|
* Content-Length: 50
|
||||||
|
*
|
||||||
|
* 2. Different order
|
||||||
|
* Content-Length: 50
|
||||||
|
* Content-Type: text/html
|
||||||
|
*
|
||||||
|
* 3. Different case
|
||||||
|
* content-type: text/html
|
||||||
|
* content-length: 50
|
||||||
|
*
|
||||||
|
* 4. Different values
|
||||||
|
* Content-Type: text/html
|
||||||
|
* Content-Length: 050
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* Applications that require semantically equal headers should convert them into a canonical form
|
||||||
|
* before comparing them for equality.
|
||||||
|
*/
|
||||||
|
@Override public boolean equals(Object other) {
|
||||||
|
return other instanceof Headers
|
||||||
|
&& Arrays.equals(((Headers) other).namesAndValues, namesAndValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public int hashCode() {
|
||||||
|
return Arrays.hashCode(namesAndValues);
|
||||||
|
}
|
||||||
|
|
||||||
@Override public String toString() {
|
@Override public String toString() {
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
for (int i = 0, size = size(); i < size; i++) {
|
for (int i = 0, size = size(); i < size; i++) {
|
||||||
@@ -122,9 +159,9 @@ public final class Headers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, List<String>> toMultimap() {
|
public Map<String, List<String>> toMultimap() {
|
||||||
Map<String, List<String>> result = new LinkedHashMap<String, List<String>>();
|
Map<String, List<String>> result = new LinkedHashMap<>();
|
||||||
for (int i = 0, size = size(); i < size; i++) {
|
for (int i = 0, size = size(); i < size; i++) {
|
||||||
String name = name(i);
|
String name = name(i).toLowerCase(Locale.US);
|
||||||
List<String> values = result.get(name);
|
List<String> values = result.get(name);
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
values = new ArrayList<>(2);
|
values = new ArrayList<>(2);
|
||||||
|
@@ -46,6 +46,8 @@ public final class Response {
|
|||||||
private Response networkResponse;
|
private Response networkResponse;
|
||||||
private Response cacheResponse;
|
private Response cacheResponse;
|
||||||
private final Response priorResponse;
|
private final Response priorResponse;
|
||||||
|
private final long sentRequestAtMillis;
|
||||||
|
private final long receivedResponseAtMillis;
|
||||||
|
|
||||||
private volatile CacheControl cacheControl; // Lazily initialized.
|
private volatile CacheControl cacheControl; // Lazily initialized.
|
||||||
|
|
||||||
@@ -60,6 +62,8 @@ public final class Response {
|
|||||||
this.networkResponse = builder.networkResponse;
|
this.networkResponse = builder.networkResponse;
|
||||||
this.cacheResponse = builder.cacheResponse;
|
this.cacheResponse = builder.cacheResponse;
|
||||||
this.priorResponse = builder.priorResponse;
|
this.priorResponse = builder.priorResponse;
|
||||||
|
this.sentRequestAtMillis = builder.sentRequestAtMillis;
|
||||||
|
this.receivedResponseAtMillis = builder.receivedResponseAtMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -238,6 +242,24 @@ public final class Response {
|
|||||||
return result != null ? result : (cacheControl = CacheControl.parse(headers));
|
return result != null ? result : (cacheControl = CacheControl.parse(headers));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@linkplain System#currentTimeMillis() timestamp} taken immediately before OkHttp
|
||||||
|
* transmitted the initiating request over the network. If this response is being served from the
|
||||||
|
* cache then this is the timestamp of the original request.
|
||||||
|
*/
|
||||||
|
public long sentRequestAtMillis() {
|
||||||
|
return sentRequestAtMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@linkplain System#currentTimeMillis() timestamp} taken immediately after OkHttp
|
||||||
|
* received this response's headers from the network. If this response is being served from the
|
||||||
|
* cache then this is the timestamp of the original response.
|
||||||
|
*/
|
||||||
|
public long receivedResponseAtMillis() {
|
||||||
|
return receivedResponseAtMillis;
|
||||||
|
}
|
||||||
|
|
||||||
@Override public String toString() {
|
@Override public String toString() {
|
||||||
return "Response{protocol="
|
return "Response{protocol="
|
||||||
+ protocol
|
+ protocol
|
||||||
@@ -261,6 +283,8 @@ public final class Response {
|
|||||||
private Response networkResponse;
|
private Response networkResponse;
|
||||||
private Response cacheResponse;
|
private Response cacheResponse;
|
||||||
private Response priorResponse;
|
private Response priorResponse;
|
||||||
|
private long sentRequestAtMillis;
|
||||||
|
private long receivedResponseAtMillis;
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
headers = new Headers.Builder();
|
headers = new Headers.Builder();
|
||||||
@@ -277,6 +301,8 @@ public final class Response {
|
|||||||
this.networkResponse = response.networkResponse;
|
this.networkResponse = response.networkResponse;
|
||||||
this.cacheResponse = response.cacheResponse;
|
this.cacheResponse = response.cacheResponse;
|
||||||
this.priorResponse = response.priorResponse;
|
this.priorResponse = response.priorResponse;
|
||||||
|
this.sentRequestAtMillis = response.sentRequestAtMillis;
|
||||||
|
this.receivedResponseAtMillis = response.receivedResponseAtMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder request(Request request) {
|
public Builder request(Request request) {
|
||||||
@@ -374,6 +400,16 @@ public final class Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder sentRequestAtMillis(long sentRequestAtMillis) {
|
||||||
|
this.sentRequestAtMillis = sentRequestAtMillis;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder receivedResponseAtMillis(long receivedResponseAtMillis) {
|
||||||
|
this.receivedResponseAtMillis = receivedResponseAtMillis;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Response build() {
|
public Response build() {
|
||||||
if (request == null) throw new IllegalStateException("request == null");
|
if (request == null) throw new IllegalStateException("request == null");
|
||||||
if (protocol == null) throw new IllegalStateException("protocol == null");
|
if (protocol == null) throw new IllegalStateException("protocol == null");
|
||||||
|
@@ -138,6 +138,8 @@ public final class CacheStrategy {
|
|||||||
this.cacheResponse = cacheResponse;
|
this.cacheResponse = cacheResponse;
|
||||||
|
|
||||||
if (cacheResponse != null) {
|
if (cacheResponse != null) {
|
||||||
|
this.sentRequestMillis = cacheResponse.sentRequestAtMillis();
|
||||||
|
this.receivedResponseMillis = cacheResponse.receivedResponseAtMillis();
|
||||||
Headers headers = cacheResponse.headers();
|
Headers headers = cacheResponse.headers();
|
||||||
for (int i = 0, size = headers.size(); i < size; i++) {
|
for (int i = 0, size = headers.size(); i < size; i++) {
|
||||||
String fieldName = headers.name(i);
|
String fieldName = headers.name(i);
|
||||||
@@ -154,10 +156,6 @@ public final class CacheStrategy {
|
|||||||
etag = value;
|
etag = value;
|
||||||
} else if ("Age".equalsIgnoreCase(fieldName)) {
|
} else if ("Age".equalsIgnoreCase(fieldName)) {
|
||||||
ageSeconds = HeaderParser.parseSeconds(value, -1);
|
ageSeconds = HeaderParser.parseSeconds(value, -1);
|
||||||
} else if (OkHeaders.SENT_MILLIS.equalsIgnoreCase(fieldName)) {
|
|
||||||
sentRequestMillis = Long.parseLong(value);
|
|
||||||
} else if (OkHeaders.RECEIVED_MILLIS.equalsIgnoreCase(fieldName)) {
|
|
||||||
receivedResponseMillis = Long.parseLong(value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -220,6 +220,8 @@ public final class HttpEngine {
|
|||||||
.code(504)
|
.code(504)
|
||||||
.message("Unsatisfiable Request (only-if-cached)")
|
.message("Unsatisfiable Request (only-if-cached)")
|
||||||
.body(EMPTY_BODY)
|
.body(EMPTY_BODY)
|
||||||
|
.sentRequestAtMillis(sentRequestMillis)
|
||||||
|
.receivedResponseAtMillis(System.currentTimeMillis())
|
||||||
.build();
|
.build();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -386,7 +388,7 @@ public final class HttpEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Offer this request to the cache.
|
// Offer this request to the cache.
|
||||||
storeRequest = responseCache.put(stripBody(userResponse));
|
storeRequest = responseCache.put(userResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -615,7 +617,7 @@ public final class HttpEngine {
|
|||||||
// Content-Encoding header (as performed by initContentStream()).
|
// Content-Encoding header (as performed by initContentStream()).
|
||||||
InternalCache responseCache = Internal.instance.internalCache(client);
|
InternalCache responseCache = Internal.instance.internalCache(client);
|
||||||
responseCache.trackConditionalCacheHit();
|
responseCache.trackConditionalCacheHit();
|
||||||
responseCache.update(cacheResponse, stripBody(userResponse));
|
responseCache.update(cacheResponse, userResponse);
|
||||||
userResponse = unzip(userResponse);
|
userResponse = unzip(userResponse);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@@ -726,8 +728,8 @@ public final class HttpEngine {
|
|||||||
Response networkResponse = httpStream.readResponseHeaders()
|
Response networkResponse = httpStream.readResponseHeaders()
|
||||||
.request(networkRequest)
|
.request(networkRequest)
|
||||||
.handshake(streamAllocation.connection().handshake())
|
.handshake(streamAllocation.connection().handshake())
|
||||||
.header(OkHeaders.SENT_MILLIS, Long.toString(sentRequestMillis))
|
.sentRequestAtMillis(sentRequestMillis)
|
||||||
.header(OkHeaders.RECEIVED_MILLIS, Long.toString(System.currentTimeMillis()))
|
.receivedResponseAtMillis(System.currentTimeMillis())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (!forWebSocket) {
|
if (!forWebSocket) {
|
||||||
|
Reference in New Issue
Block a user