diff --git a/okhttp/src/main/java/com/squareup/okhttp/Request.java b/okhttp/src/main/java/com/squareup/okhttp/Request.java index 7cd16170f..780b889ac 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/Request.java +++ b/okhttp/src/main/java/com/squareup/okhttp/Request.java @@ -118,10 +118,7 @@ public final class Request { } public Builder newBuilder() { - return new Builder(url) - .method(method, body) - .headers(headers) - .tag(tag); + return new Builder(this); } public boolean isChunked() { @@ -397,23 +394,27 @@ public final class Request { public static class Builder { private URL url; - private String method = "GET"; - private Headers.Builder headers = new Headers.Builder(); + private String method; + private final Headers.Builder headers; private Body body; private Object tag; - public Builder(String url) { - url(url); + public Builder() { + this.method = "GET"; + this.headers = new Headers.Builder(); } - public Builder(URL url) { - url(url); + private Builder(Request request) { + this.url = request.url; + this.method = request.method; + this.body = request.body; + this.tag = request.tag; + this.headers = request.headers.newBuilder(); } public Builder url(String url) { try { - this.url = new URL(url); - return this; + return url(new URL(url)); } catch (MalformedURLException e) { throw new IllegalArgumentException("Malformed URL: " + url); } @@ -443,12 +444,6 @@ public final class Request { return this; } - // TODO: this shouldn't be public. - public Builder headers(Headers headers) { - this.headers = headers.newBuilder(); - return this; - } - public Builder setChunked() { headers.set("Transfer-Encoding", "chunked"); return this; @@ -514,25 +509,6 @@ public final class Request { return sb.toString(); } - // TODO: this shouldn't be public. - /** - * @param method like "GET", "POST", "HEAD", etc. - * @param path like "/foo/bar.html" - * @param version like "HTTP/1.1" - * @param host like "www.android.com:1234" - * @param scheme like "https" - */ - public Builder addSpdyRequestHeaders( - String method, String path, String version, String host, String scheme) { - // TODO: populate the statusLine for the client's benefit? - headers.set(":method", method); - headers.set(":scheme", scheme); - headers.set(":path", path); - headers.set(":version", version); - headers.set(":host", host); - return this; - } - public Builder get() { return method("GET", null); } @@ -569,6 +545,7 @@ public final class Request { } public Request build() { + if (url == null) throw new IllegalStateException("url == null"); return new Request(this); } } diff --git a/okhttp/src/main/java/com/squareup/okhttp/Response.java b/okhttp/src/main/java/com/squareup/okhttp/Response.java index 36b444c01..059621034 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/Response.java +++ b/okhttp/src/main/java/com/squareup/okhttp/Response.java @@ -15,11 +15,11 @@ */ package com.squareup.okhttp; -import com.squareup.okhttp.internal.Platform; import com.squareup.okhttp.internal.Util; import com.squareup.okhttp.internal.http.HeaderParser; import com.squareup.okhttp.internal.http.Headers; import com.squareup.okhttp.internal.http.HttpDate; +import com.squareup.okhttp.internal.http.SyntheticHeaders; import com.squareup.okhttp.internal.http.StatusLine; import java.io.ByteArrayOutputStream; import java.io.Closeable; @@ -47,21 +47,6 @@ import static com.squareup.okhttp.internal.Util.equal; * This class is in beta. APIs are subject to change! */ public final class Response { - /** HTTP header name for the local time when the request was sent. */ - private static final String SENT_MILLIS = Platform.get().getPrefix() + "-Sent-Millis"; - - /** HTTP header name for the local time when the response was received. */ - private static final String RECEIVED_MILLIS = Platform.get().getPrefix() + "-Received-Millis"; - - /** HTTP synthetic header with the response source. */ - // TODO: this shouldn't be public. - public static final String RESPONSE_SOURCE = Platform.get().getPrefix() + "-Response-Source"; - - /** HTTP synthetic header with the selected transport (spdy/3, http/1.1, etc). */ - // TODO: this shouldn't be public. - public static final String SELECTED_TRANSPORT - = Platform.get().getPrefix() + "-Selected-Transport"; - private final Request request; private final StatusLine statusLine; private final Handshake handshake; @@ -561,9 +546,9 @@ public final class Response { contentType = value; } else if ("Connection".equalsIgnoreCase(fieldName)) { connection = value; - } else if (SENT_MILLIS.equalsIgnoreCase(fieldName)) { + } else if (SyntheticHeaders.SENT_MILLIS.equalsIgnoreCase(fieldName)) { sentRequestMillis = Long.parseLong(value); - } else if (RECEIVED_MILLIS.equalsIgnoreCase(fieldName)) { + } else if (SyntheticHeaders.RECEIVED_MILLIS.equalsIgnoreCase(fieldName)) { receivedResponseMillis = Long.parseLong(value); } } @@ -691,14 +676,14 @@ public final class Response { // TODO: this shouldn't be public. public Builder setLocalTimestamps(long sentRequestMillis, long receivedResponseMillis) { - headers.set(SENT_MILLIS, Long.toString(sentRequestMillis)); - headers.set(RECEIVED_MILLIS, Long.toString(receivedResponseMillis)); + headers.set(SyntheticHeaders.SENT_MILLIS, Long.toString(sentRequestMillis)); + headers.set(SyntheticHeaders.RECEIVED_MILLIS, Long.toString(receivedResponseMillis)); return this; } // TODO: this shouldn't be public. public Builder setResponseSource(ResponseSource responseSource) { - headers.set(RESPONSE_SOURCE, responseSource.toString() + " " + statusLine.code()); + headers.set(SyntheticHeaders.RESPONSE_SOURCE, responseSource + " " + statusLine.code()); return this; } diff --git a/okhttp/src/main/java/com/squareup/okhttp/ResponseSource.java b/okhttp/src/main/java/com/squareup/okhttp/ResponseSource.java index 4eca172d3..dbe17cb47 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/ResponseSource.java +++ b/okhttp/src/main/java/com/squareup/okhttp/ResponseSource.java @@ -29,7 +29,14 @@ public enum ResponseSource { CONDITIONAL_CACHE, /** The response was returned from the network. */ - NETWORK; + NETWORK, + + /** + * The request demanded a cached response that the cache couldn't satisfy. + * This yields a 504 (Gateway Timeout) response as specified by + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4. + */ + NONE; public boolean requiresConnection() { return this == CONDITIONAL_CACHE || this == NETWORK; diff --git a/okhttp/src/main/java/com/squareup/okhttp/TunnelRequest.java b/okhttp/src/main/java/com/squareup/okhttp/TunnelRequest.java index 7efc422db..3bcff5a8a 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/TunnelRequest.java +++ b/okhttp/src/main/java/com/squareup/okhttp/TunnelRequest.java @@ -60,7 +60,8 @@ public final class TunnelRequest { * the proxy unencrypted. */ Request getRequest() throws IOException { - Request.Builder result = new Request.Builder(new URL("https", host, port, "/")); + Request.Builder result = new Request.Builder() + .url(new URL("https", host, port, "/")); // Always set Host and User-Agent. result.header("Host", port == getDefaultPort("https") ? host : (host + ":" + port)); diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/ResponseStrategy.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java similarity index 87% rename from okhttp/src/main/java/com/squareup/okhttp/internal/http/ResponseStrategy.java rename to okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java index f8521edc0..5be92a820 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/ResponseStrategy.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java @@ -7,16 +7,19 @@ import java.net.HttpURLConnection; import java.util.concurrent.TimeUnit; /** - * Given a request and cached response, this figures out the next action. It - * may also update the request to add conditions, or the response to add - * warnings. + * Given a request and cached response, this figures out whether to use the + * network, the cache, or both. + * + *

Selecting the next action may have side effects. The request may gain + * conditions such as an "If-None-Match" or "If-Modified-Since" header. The + * response may gain a warning if it is potentially stale. */ -public final class ResponseStrategy { +public final class CacheStrategy { public final Request request; public final Response response; public final ResponseSource source; - private ResponseStrategy( + private CacheStrategy( Request request, Response response, ResponseSource source) { this.request = request; this.response = response; @@ -111,17 +114,17 @@ public final class ResponseStrategy { * Returns a strategy to satisfy {@code request} using the a cached response * {@code response}. */ - public static ResponseStrategy get( + public static CacheStrategy get( long nowMillis, Response response, Request request) { // If this response shouldn't have been stored, it should never be used // as a response source. This check should be redundant as long as the // persistence store is well-behaved and the rules are constant. if (!isCacheable(response, request)) { - return new ResponseStrategy(request, response, ResponseSource.NETWORK); + return new CacheStrategy(request, response, ResponseSource.NETWORK); } if (request.isNoCache() || request.hasConditions()) { - return new ResponseStrategy(request, response, ResponseSource.NETWORK); + return new CacheStrategy(request, response, ResponseSource.NETWORK); } long ageMillis = computeAge(response, nowMillis); @@ -142,7 +145,8 @@ public final class ResponseStrategy { } if (!response.isNoCache() && ageMillis + minFreshMillis < freshMillis + maxStaleMillis) { - Response.Builder builder = response.newBuilder(); + Response.Builder builder = response.newBuilder() + .setResponseSource(ResponseSource.CACHE); // Overwrite any stored response source. if (ageMillis + minFreshMillis >= freshMillis) { builder.addWarning("110 HttpURLConnection \"Response is stale\""); } @@ -150,7 +154,7 @@ public final class ResponseStrategy { if (ageMillis > oneDayMillis && isFreshnessLifetimeHeuristic(response)) { builder.addWarning("113 HttpURLConnection \"Heuristic expiration\""); } - return new ResponseStrategy(request, builder.build(), ResponseSource.CACHE); + return new CacheStrategy(request, builder.build(), ResponseSource.CACHE); } Request.Builder conditionalRequestBuilder = request.newBuilder(); @@ -169,6 +173,6 @@ public final class ResponseStrategy { ResponseSource responseSource = conditionalRequest.hasConditions() ? ResponseSource.CONDITIONAL_CACHE : ResponseSource.NETWORK; - return new ResponseStrategy(conditionalRequest, response, responseSource); + return new CacheStrategy(conditionalRequest, response, responseSource); } } diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java index 99d690da4..2d2f5fac8 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java @@ -27,7 +27,6 @@ import com.squareup.okhttp.Response; import com.squareup.okhttp.ResponseSource; import com.squareup.okhttp.TunnelRequest; import com.squareup.okhttp.internal.Dns; -import com.squareup.okhttp.internal.Util; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -40,6 +39,7 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSocketFactory; import static com.squareup.okhttp.internal.Util.EMPTY_INPUT_STREAM; +import static com.squareup.okhttp.internal.Util.closeQuietly; import static com.squareup.okhttp.internal.Util.getDefaultPort; import static com.squareup.okhttp.internal.Util.getEffectivePort; import static com.squareup.okhttp.internal.http.StatusLine.HTTP_CONTINUE; @@ -155,33 +155,10 @@ public class HttpEngine { * writing the request body if it exists. */ public final void sendRequest() throws IOException { - if (responseSource != null) { - return; - } + if (responseSource != null) return; prepareRawRequestHeaders(); - initResponseSource(); - OkResponseCache responseCache = client.getOkResponseCache(); - if (responseCache != null) { - responseCache.trackResponse(responseSource); - } - - // The raw response source may require the network, but the request - // headers may forbid network use. In that case, dispose of the network - // response and use a gateway timeout response instead, as specified - // by http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4. - if (request.isOnlyIfCached() && responseSource.requiresConnection()) { - if (responseSource == ResponseSource.CONDITIONAL_CACHE) { - Util.closeQuietly(validatingResponse.body()); - } - this.responseSource = ResponseSource.CACHE; - - this.validatingResponse = new Response.Builder(request) - .statusLine(new StatusLine("HTTP/1.1 504 Gateway Timeout")) - .body(EMPTY_BODY) - .build(); - promoteValidatingResponse(); - } + responseSource = chooseResponseSource(); if (responseSource.requiresConnection()) { sendSocketRequest(); @@ -191,38 +168,56 @@ public class HttpEngine { } } - /** - * Initialize the source for this response. It may be corrected later if the - * request headers forbids network use. - */ - private void initResponseSource() throws IOException { - responseSource = ResponseSource.NETWORK; - + /** Returns a source that can satisfy the request. */ + private ResponseSource chooseResponseSource() throws IOException { OkResponseCache responseCache = client.getOkResponseCache(); - if (responseCache == null) return; + if (responseCache == null) return ResponseSource.NETWORK; // No cache? Easy decision. Response candidate = responseCache.get(request); - if (candidate == null) return; - // Drop the cached response if it's missing a required handshake. - if (request.isHttps() && candidate.handshake() == null) { - Util.closeQuietly(candidate.body()); - return; + ResponseSource result; + if (candidate == null) { + result = ResponseSource.NETWORK; + + } else if (request.isHttps() && candidate.handshake() == null) { + // Drop the cached response if it's missing a required handshake. + result = ResponseSource.NETWORK; + + } else { + // We've got a lead on a cached response. Ask response strategy to analyze it. + long now = System.currentTimeMillis(); + CacheStrategy cacheStrategy = CacheStrategy.get(now, candidate, request); + result = cacheStrategy.source; + this.request = cacheStrategy.request; + + if (result == ResponseSource.CACHE || result == ResponseSource.CONDITIONAL_CACHE) { + this.validatingResponse = cacheStrategy.response; + } } - long now = System.currentTimeMillis(); - ResponseStrategy responseStrategy = ResponseStrategy.get(now, candidate, request); - this.responseSource = responseStrategy.source; - this.request = responseStrategy.request; + if (candidate != null && result == ResponseSource.NETWORK) { + closeQuietly(candidate.body()); // We aren't using the cached response. Close it. + } - if (responseSource == ResponseSource.CACHE) { - this.validatingResponse = responseStrategy.response; + if (result == ResponseSource.CACHE) { + promoteValidatingResponse(); + } else if (request.isOnlyIfCached()) { + // We're forbidden from using the network, but the cache is insufficient. + if (result == ResponseSource.CONDITIONAL_CACHE) { + closeQuietly(validatingResponse.body()); + } + + result = ResponseSource.NONE; + this.validatingResponse = new Response.Builder(request) + .statusLine(new StatusLine("HTTP/1.1 504 Gateway Timeout")) + .setResponseSource(result) + .body(EMPTY_BODY) + .build(); promoteValidatingResponse(); - } else if (responseSource == ResponseSource.CONDITIONAL_CACHE) { - this.validatingResponse = responseStrategy.response; - } else if (responseSource == ResponseSource.NETWORK) { - Util.closeQuietly(candidate.body()); } + + responseCache.trackResponse(result); + return result; } private Response cacheableResponse() { @@ -314,9 +309,7 @@ public class HttpEngine { /** Returns the request body or null if this request doesn't have a body. */ public final OutputStream getRequestBody() { - if (responseSource == null) { - throw new IllegalStateException(); - } + if (responseSource == null) throw new IllegalStateException(); return requestBodyOut; } @@ -349,7 +342,7 @@ public class HttpEngine { if (responseCache == null) return; // Should we cache this response for this request? - if (!ResponseStrategy.isCacheable(response, request)) { + if (!CacheStrategy.isCacheable(response, request)) { responseCache.maybeRemove(request); return; } @@ -382,7 +375,7 @@ public class HttpEngine { if (validatingResponse != null && validatingResponse.body() != null && responseBodyIn == validatingResponse.body().byteStream()) { - Util.closeQuietly(responseBodyIn); + closeQuietly(responseBodyIn); } if (!connectionReleased && connection != null) { @@ -390,7 +383,7 @@ public class HttpEngine { if (transport == null || !transport.makeReusable(streamCanceled, requestBodyOut, responseTransferIn)) { - Util.closeQuietly(connection); + closeQuietly(connection); connection = null; } else if (automaticallyReleaseConnectionToPool) { client.getConnectionPool().recycle(connection); @@ -460,7 +453,7 @@ public class HttpEngine { } if (request.getHost() == null) { - result.setHost(getHostHeader(request.url())); + result.setHost(hostHeader(request.url())); } if ((connection == null || connection.getHttpMinorVersion() != 0) @@ -490,7 +483,7 @@ public class HttpEngine { return agent != null ? agent : ("Java" + System.getProperty("java.version")); } - public static String getHostHeader(URL url) { + public static String hostHeader(URL url) { return getEffectivePort(url) != getDefaultPort(url.getProtocol()) ? url.getHost() + ":" + url.getPort() : url.getHost(); @@ -501,19 +494,9 @@ public class HttpEngine { * headers and starts reading the HTTP response body if it exists. */ public final void readResponse() throws IOException { - if (hasResponse()) { - // TODO: this doesn't make much sense. - response = response.newBuilder().setResponseSource(responseSource).build(); - return; - } - - if (responseSource == null) { - throw new IllegalStateException("readResponse() without sendRequest()"); - } - - if (!responseSource.requiresConnection()) { - return; - } + if (response != null) return; + if (responseSource == null) throw new IllegalStateException("call sendRequest() first!"); + if (!responseSource.requiresConnection()) return; if (sentRequestMillis == -1) { if (request.getContentLength() == -1 @@ -556,7 +539,7 @@ public class HttpEngine { } return; } else { - Util.closeQuietly(validatingResponse.body()); + closeQuietly(validatingResponse.body()); } } diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpTransport.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpTransport.java index 64ed3c1ee..7a98b9626 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpTransport.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpTransport.java @@ -174,7 +174,7 @@ public final class HttpTransport implements Transport { Response.Builder responseBuilder = new Response.Builder(request); responseBuilder.statusLine(statusLine); - responseBuilder.header(Response.SELECTED_TRANSPORT, "http/1.1"); + responseBuilder.header(SyntheticHeaders.SELECTED_TRANSPORT, "http/1.1"); Headers.Builder headersBuilder = new Headers.Builder(); headersBuilder.readHeaders(in); diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java index 6b2565f05..cb13100a2 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java @@ -172,7 +172,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy { } // For the request line property assigned to the null key, just use no proxy and HTTP 1.1. - Request request = new Request.Builder(getURL()).method(method, null).build(); + Request request = new Request.Builder().url(getURL()).method(method, null).build(); String requestLine = RequestLine.get(request, null, 1); return requestHeaders.build().toMultimap(requestLine); } @@ -271,10 +271,14 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy { private HttpEngine newHttpEngine(String method, Connection connection, RetryableOutputStream requestBody) throws IOException { - Request request = new Request.Builder(getURL()) - .method(method, null) // No body: that's provided later! - .headers(requestHeaders.build()) - .build(); + Request.Builder builder = new Request.Builder() + .url(getURL()) + .method(method, null /* No body; that's passed separately. */); + Headers headers = requestHeaders.build(); + for (int i = 0; i < headers.length(); i++) { + builder.addHeader(headers.getFieldName(i), headers.getValue(i)); + } + Request request = builder.build(); // If we're currently not using caches, make sure the engine's client doesn't have one. OkHttpClient engineClient = client; diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java index 5f35582c0..2118830b3 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java @@ -26,7 +26,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.CacheRequest; import java.net.ProtocolException; -import java.net.URL; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; @@ -44,12 +43,12 @@ public final class SpdyTransport implements Transport { } @Override public Request prepareRequest(Request request) { - Request.Builder builder = request.newBuilder(); - - String version = RequestLine.version(httpEngine.connection.getHttpMinorVersion()); - URL url = request.url(); - builder.addSpdyRequestHeaders(request.method(), RequestLine.requestPath(url), version, - HttpEngine.getHostHeader(url), httpEngine.getRequest().url().getProtocol()); + Request.Builder builder = request.newBuilder() + .header(":method", request.method()) + .header(":scheme", httpEngine.getRequest().url().getProtocol()) + .header(":path", RequestLine.requestPath(request.url())) + .header(":version", RequestLine.version(httpEngine.connection.getHttpMinorVersion())) + .header(":host", HttpEngine.hostHeader(request.url())); if (httpEngine.hasRequestBody()) { long fixedContentLength = httpEngine.policy.getFixedContentLength(); @@ -145,7 +144,7 @@ public final class SpdyTransport implements Transport { String version = null; Headers.Builder headersBuilder = new Headers.Builder(); - headersBuilder.set(Response.SELECTED_TRANSPORT, "spdy/3"); + headersBuilder.set(SyntheticHeaders.SELECTED_TRANSPORT, "spdy/3"); for (int i = 0; i < nameValueBlock.size(); i += 2) { String name = nameValueBlock.get(i); String values = nameValueBlock.get(i + 1); diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/SyntheticHeaders.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/SyntheticHeaders.java new file mode 100644 index 000000000..fbb633d65 --- /dev/null +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/SyntheticHeaders.java @@ -0,0 +1,23 @@ +package com.squareup.okhttp.internal.http; + +import com.squareup.okhttp.internal.Platform; + +/** Headers added to the HTTP response for internal use by OkHttp. */ +public final class SyntheticHeaders { + static final String PREFIX = Platform.get().getPrefix(); + + /** The local time when the request was sent. */ + public static final String SENT_MILLIS = PREFIX + "-Sent-Millis"; + + /** The local time when the response was received. */ + public static final String RECEIVED_MILLIS = PREFIX + "-Received-Millis"; + + /** The response source. */ + public static final String RESPONSE_SOURCE = PREFIX + "-Response-Source"; + + /** The selected transport (spdy/3, http/1.1, etc). */ + public static final String SELECTED_TRANSPORT = PREFIX + "-Selected-Transport"; + + private SyntheticHeaders() { + } +} diff --git a/okhttp/src/test/java/com/squareup/okhttp/AsyncApiTest.java b/okhttp/src/test/java/com/squareup/okhttp/AsyncApiTest.java index 849fb8b58..e21f93877 100644 --- a/okhttp/src/test/java/com/squareup/okhttp/AsyncApiTest.java +++ b/okhttp/src/test/java/com/squareup/okhttp/AsyncApiTest.java @@ -57,7 +57,8 @@ public final class AsyncApiTest { .addHeader("Content-Type: text/plain")); server.play(); - Request request = new Request.Builder(server.getUrl("/")) + Request request = new Request.Builder() + .url(server.getUrl("/")) .header("User-Agent", "AsyncApiTest") .build(); client.enqueue(request, receiver); @@ -80,7 +81,9 @@ public final class AsyncApiTest { client.setSslSocketFactory(sslContext.getSocketFactory()); client.setHostnameVerifier(new RecordingHostnameVerifier()); - Request request = new Request.Builder(server.getUrl("/")).build(); + Request request = new Request.Builder() + .url(server.getUrl("/")) + .build(); client.enqueue(request, receiver); receiver.await(request.url()).assertHandshake(); @@ -90,7 +93,8 @@ public final class AsyncApiTest { server.enqueue(new MockResponse().setBody("abc")); server.play(); - Request request = new Request.Builder(server.getUrl("/")) + Request request = new Request.Builder() + .url(server.getUrl("/")) .post(Request.Body.create(MediaType.parse("text/plain"), "def")) .build(); client.enqueue(request, receiver); @@ -112,12 +116,16 @@ public final class AsyncApiTest { client.setOkResponseCache(cache); - Request request1 = new Request.Builder(server.getUrl("/")).build(); + Request request1 = new Request.Builder() + .url(server.getUrl("/")) + .build(); client.enqueue(request1, receiver); receiver.await(request1.url()).assertCode(200).assertBody("A"); assertNull(server.takeRequest().getHeader("If-None-Match")); - Request request2 = new Request.Builder(server.getUrl("/")).build(); + Request request2 = new Request.Builder() + .url(server.getUrl("/")) + .build(); client.enqueue(request2, receiver); receiver.await(request2.url()).assertCode(200).assertBody("A"); assertEquals("v1", server.takeRequest().getHeader("If-None-Match")); diff --git a/okhttp/src/test/java/com/squareup/okhttp/internal/http/HeadersTest.java b/okhttp/src/test/java/com/squareup/okhttp/internal/http/HeadersTest.java index d815d431d..8c0c30ad4 100644 --- a/okhttp/src/test/java/com/squareup/okhttp/internal/http/HeadersTest.java +++ b/okhttp/src/test/java/com/squareup/okhttp/internal/http/HeadersTest.java @@ -32,15 +32,15 @@ public final class HeadersTest { "set-cookie", "Cookie1\u0000Cookie2", ":status", "200 OK", ":version", "HTTP/1.1"); - Request request = new Request.Builder("http://square.com/").build(); + Request request = new Request.Builder().url("http://square.com/").build(); Response response = SpdyTransport.readNameValueBlock(request, nameValueBlock).build(); Headers headers = response.headers(); assertEquals(4, headers.length()); assertEquals("HTTP/1.1 200 OK", response.statusLine()); assertEquals("no-cache, no-store", headers.get("cache-control")); assertEquals("Cookie2", headers.get("set-cookie")); - assertEquals("spdy/3", headers.get(Response.SELECTED_TRANSPORT)); - assertEquals(Response.SELECTED_TRANSPORT, headers.getFieldName(0)); + assertEquals("spdy/3", headers.get(SyntheticHeaders.SELECTED_TRANSPORT)); + assertEquals(SyntheticHeaders.SELECTED_TRANSPORT, headers.getFieldName(0)); assertEquals("spdy/3", headers.getValue(0)); assertEquals("cache-control", headers.getFieldName(1)); assertEquals("no-cache, no-store", headers.getValue(1)); diff --git a/okhttp/src/test/java/com/squareup/okhttp/internal/http/HttpResponseCacheTest.java b/okhttp/src/test/java/com/squareup/okhttp/internal/http/HttpResponseCacheTest.java index 06b6e5142..946c4084e 100644 --- a/okhttp/src/test/java/com/squareup/okhttp/internal/http/HttpResponseCacheTest.java +++ b/okhttp/src/test/java/com/squareup/okhttp/internal/http/HttpResponseCacheTest.java @@ -204,7 +204,7 @@ public final class HttpResponseCacheTest { // exhaust the content stream readAscii(conn); - Response cached = cache.get(new Request.Builder(url).build()); + Response cached = cache.get(new Request.Builder().url(url).build()); if (shouldPut) { assertNotNull(Integer.toString(responseCode), cached); cached.body().close(); @@ -1048,6 +1048,9 @@ public final class HttpResponseCacheTest { HttpURLConnection connection = openConnection(server.getUrl("/")); connection.addRequestProperty("Cache-Control", "only-if-cached"); assertGatewayTimeout(connection); + assertEquals(1, cache.getRequestCount()); + assertEquals(0, cache.getNetworkCount()); + assertEquals(0, cache.getHitCount()); } @Test public void requestOnlyIfCachedWithFullResponseCached() throws IOException { @@ -1060,6 +1063,9 @@ public final class HttpResponseCacheTest { URLConnection connection = openConnection(server.getUrl("/")); connection.addRequestProperty("Cache-Control", "only-if-cached"); assertEquals("A", readAscii(connection)); + assertEquals(2, cache.getRequestCount()); + assertEquals(1, cache.getNetworkCount()); + assertEquals(1, cache.getHitCount()); } @Test public void requestOnlyIfCachedWithConditionalResponseCached() throws IOException { @@ -1072,6 +1078,9 @@ public final class HttpResponseCacheTest { HttpURLConnection connection = openConnection(server.getUrl("/")); connection.addRequestProperty("Cache-Control", "only-if-cached"); assertGatewayTimeout(connection); + assertEquals(2, cache.getRequestCount()); + assertEquals(1, cache.getNetworkCount()); + assertEquals(0, cache.getHitCount()); } @Test public void requestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException { @@ -1082,6 +1091,9 @@ public final class HttpResponseCacheTest { HttpURLConnection connection = openConnection(server.getUrl("/")); connection.addRequestProperty("Cache-Control", "only-if-cached"); assertGatewayTimeout(connection); + assertEquals(2, cache.getRequestCount()); + assertEquals(1, cache.getNetworkCount()); + assertEquals(0, cache.getHitCount()); } @Test public void requestCacheControlNoCache() throws Exception { @@ -1684,8 +1696,8 @@ public final class HttpResponseCacheTest { connection.addRequestProperty("Cache-Control", "only-if-cached"); assertEquals("A", readAscii(connection)); - String source = connection.getHeaderField(Response.RESPONSE_SOURCE); - assertEquals(ResponseSource.CACHE.toString() + " 200", source); + String source = connection.getHeaderField(SyntheticHeaders.RESPONSE_SOURCE); + assertEquals(ResponseSource.CACHE + " 200", source); } @Test public void responseSourceHeaderConditionalCacheFetched() throws IOException { @@ -1701,8 +1713,8 @@ public final class HttpResponseCacheTest { HttpURLConnection connection = openConnection(server.getUrl("/")); assertEquals("B", readAscii(connection)); - String source = connection.getHeaderField(Response.RESPONSE_SOURCE); - assertEquals(ResponseSource.CONDITIONAL_CACHE.toString() + " 200", source); + String source = connection.getHeaderField(SyntheticHeaders.RESPONSE_SOURCE); + assertEquals(ResponseSource.CONDITIONAL_CACHE + " 200", source); } @Test public void responseSourceHeaderConditionalCacheNotFetched() throws IOException { @@ -1716,8 +1728,8 @@ public final class HttpResponseCacheTest { HttpURLConnection connection = openConnection(server.getUrl("/")); assertEquals("A", readAscii(connection)); - String source = connection.getHeaderField(Response.RESPONSE_SOURCE); - assertEquals(ResponseSource.CONDITIONAL_CACHE.toString() + " 304", source); + String source = connection.getHeaderField(SyntheticHeaders.RESPONSE_SOURCE); + assertEquals(ResponseSource.CONDITIONAL_CACHE + " 304", source); } @Test public void responseSourceHeaderFetched() throws IOException { @@ -1727,8 +1739,8 @@ public final class HttpResponseCacheTest { URLConnection connection = openConnection(server.getUrl("/")); assertEquals("A", readAscii(connection)); - String source = connection.getHeaderField(Response.RESPONSE_SOURCE); - assertEquals(ResponseSource.NETWORK.toString() + " 200", source); + String source = connection.getHeaderField(SyntheticHeaders.RESPONSE_SOURCE); + assertEquals(ResponseSource.NETWORK + " 200", source); } @Test public void emptyResponseHeaderNameFromCacheIsLenient() throws Exception { @@ -1943,6 +1955,8 @@ public final class HttpResponseCacheTest { } assertEquals(504, connection.getResponseCode()); assertEquals(-1, connection.getErrorStream().read()); + assertEquals(ResponseSource.NONE + " 504", + connection.getHeaderField(SyntheticHeaders.RESPONSE_SOURCE)); } enum TransferKind {