1
0
mirror of https://github.com/square/okhttp.git synced 2026-01-27 04:22:07 +03:00

Merge pull request #61 from square/jwilson/fewer_statics

Move system-wide statics to the OkHttpClient class.
This commit is contained in:
Jake Wharton
2012-12-21 19:52:57 -08:00
10 changed files with 172 additions and 101 deletions

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.squareup.okhttp.internal.util;
package com.squareup.okhttp;
import java.io.IOException;
import java.net.CacheResponse;

View File

@@ -17,8 +17,11 @@ package com.squareup.okhttp;
import com.squareup.okhttp.internal.net.http.HttpURLConnectionImpl;
import com.squareup.okhttp.internal.net.http.HttpsURLConnectionImpl;
import java.net.CookieHandler;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.ResponseCache;
import java.net.URL;
/**
@@ -26,18 +29,76 @@ import java.net.URL;
*/
public final class OkHttpClient {
private Proxy proxy;
private ProxySelector proxySelector;
private CookieHandler cookieHandler;
private ResponseCache responseCache;
/**
* Sets the HTTP proxy that will be used by connections created by this
* client. This takes precedence over {@link #setProxySelector}, which is
* only honored when this proxy is null (which it is by default). To disable
* proxy use completely, call {@code setProxy(Proxy.NO_PROXY)}.
*/
public OkHttpClient setProxy(Proxy proxy) {
this.proxy = proxy;
return this;
}
/**
* Sets the proxy selection policy to be used if no {@link #setProxy proxy}
* is specified explicitly. The proxy selector may return multiple proxies;
* in that case they will be tried in sequence until a successful connection
* is established.
*
* <p>If unset, the {@link ProxySelector#getDefault() system-wide default}
* proxy selector will be used.
*/
public OkHttpClient setProxySelector(ProxySelector proxySelector) {
this.proxySelector = proxySelector;
return this;
}
/**
* Sets the cookie handler to be used to read outgoing cookies and write
* incoming cookies.
*
* <p>If unset, the {@link CookieHandler#getDefault() system-wide default}
* cookie handler will be used.
*/
public OkHttpClient setCookieHandler(CookieHandler cookieHandler) {
this.cookieHandler = cookieHandler;
return this;
}
/**
* Sets the response cache to be used to read and write cached responses.
*
* <p>If unset, the {@link ResponseCache#getDefault() system-wide default}
* response cache will be used.
*/
public OkHttpClient setResponseCache(ResponseCache responseCache) {
this.responseCache = responseCache;
return this;
}
public HttpURLConnection open(URL url) {
ProxySelector proxySelector = this.proxySelector != null
? this.proxySelector
: ProxySelector.getDefault();
CookieHandler cookieHandler = this.cookieHandler != null
? this.cookieHandler
: CookieHandler.getDefault();
ResponseCache responseCache = this.responseCache != null
? this.responseCache
: ResponseCache.getDefault();
String protocol = url.getProtocol();
if (protocol.equals("http")) {
return new HttpURLConnectionImpl(url, 80, proxy);
return new HttpURLConnectionImpl(
url, 80, proxy, proxySelector, cookieHandler, responseCache);
} else if (protocol.equals("https")) {
return new HttpsURLConnectionImpl(url, 443, proxy);
return new HttpsURLConnectionImpl(
url, 443, proxy, proxySelector, cookieHandler, responseCache);
} else {
throw new IllegalArgumentException();
}

View File

@@ -14,26 +14,27 @@
* limitations under the License.
*/
package com.squareup.okhttp.internal.util;
package com.squareup.okhttp;
/**
* Where the HTTP client should look for a response.
* The source of an HTTP response.
*/
public enum ResponseSource {
/**
* Return the response from the cache immediately.
* The response was returned from the local cache.
*/
CACHE,
/**
* Make a conditional request to the host, returning the cache response if
* the cache is valid and the network response otherwise.
* The response is available in the cache but must be validated with the
* network. The cache result will be used if it is still valid; otherwise
* the network's response will be used.
*/
CONDITIONAL_CACHE,
/**
* Return the response from the network.
* The response was returned from the network.
*/
NETWORK;

View File

@@ -17,12 +17,12 @@
package com.squareup.okhttp.internal.net.http;
import com.squareup.okhttp.ExtendedResponseCache;
import com.squareup.okhttp.ResponseSource;
import com.squareup.okhttp.internal.io.IoUtils;
import com.squareup.okhttp.internal.net.Dns;
import com.squareup.okhttp.internal.util.EmptyArray;
import com.squareup.okhttp.internal.util.ExtendedResponseCache;
import com.squareup.okhttp.internal.util.Libcore;
import com.squareup.okhttp.internal.util.ResponseSource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -32,8 +32,6 @@ import java.net.CacheResponse;
import java.net.CookieHandler;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.ResponseCache;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
@@ -107,7 +105,6 @@ public class HttpEngine {
private InputStream responseTransferIn;
private InputStream responseBodyIn;
private final ResponseCache responseCache = ResponseCache.getDefault();
private CacheResponse cacheResponse;
private CacheRequest cacheRequest;
@@ -185,8 +182,8 @@ public class HttpEngine {
prepareRawRequestHeaders();
initResponseSource();
if (responseCache instanceof ExtendedResponseCache) {
((ExtendedResponseCache) responseCache).trackResponse(responseSource);
if (policy.responseCache instanceof ExtendedResponseCache) {
((ExtendedResponseCache) policy.responseCache).trackResponse(responseSource);
}
/*
@@ -220,11 +217,11 @@ public class HttpEngine {
*/
private void initResponseSource() throws IOException {
responseSource = ResponseSource.NETWORK;
if (!policy.getUseCaches() || responseCache == null) {
if (!policy.getUseCaches() || policy.responseCache == null) {
return;
}
CacheResponse candidate = responseCache.get(uri, method,
CacheResponse candidate = policy.responseCache.get(uri, method,
requestHeaders.getHeaders().toMultimap(false));
if (candidate == null) {
return;
@@ -283,7 +280,7 @@ public class HttpEngine {
if (routeSelector == null) {
HttpConnection.Address address = new HttpConnection.Address(uri, getSslSocketFactory(),
getHostnameVerifier(), policy.getProxy());
routeSelector = new RouteSelector(address, uri, ProxySelector.getDefault(), Dns.DEFAULT);
routeSelector = new RouteSelector(address, uri, policy.proxySelector, Dns.DEFAULT);
}
connection = routeSelector.next();
if (!connection.isRecycled()) {
@@ -378,7 +375,7 @@ public class HttpEngine {
private void maybeCache() throws IOException {
// Are we caching at all?
if (!policy.getUseCaches() || responseCache == null) {
if (!policy.getUseCaches() || policy.responseCache == null) {
return;
}
@@ -388,7 +385,7 @@ public class HttpEngine {
}
// Offer this request to the cache.
cacheRequest = responseCache.put(uri, getHttpConnectionToCache());
cacheRequest = policy.responseCache.put(uri, getHttpConnectionToCache());
}
protected HttpURLConnection getHttpConnectionToCache() {
@@ -515,7 +512,7 @@ public class HttpEngine {
requestHeaders.setIfModifiedSince(new Date(ifModifiedSince));
}
CookieHandler cookieHandler = CookieHandler.getDefault();
CookieHandler cookieHandler = policy.cookieHandler;
if (cookieHandler != null) {
requestHeaders.addCookies(
cookieHandler.get(uri, requestHeaders.getHeaders().toMultimap(false)));
@@ -643,8 +640,9 @@ public class HttpEngine {
release(true);
ResponseHeaders combinedHeaders = cachedResponseHeaders.combine(responseHeaders);
setResponse(combinedHeaders, cachedResponseBody);
if (responseCache instanceof ExtendedResponseCache) {
ExtendedResponseCache httpResponseCache = (ExtendedResponseCache) responseCache;
if (policy.responseCache instanceof ExtendedResponseCache) {
ExtendedResponseCache httpResponseCache
= (ExtendedResponseCache) policy.responseCache;
httpResponseCache.trackConditionalCacheHit();
httpResponseCache.update(cacheResponse, getHttpConnectionToCache());
}

View File

@@ -21,9 +21,9 @@ import com.squareup.okhttp.internal.io.DiskLruCache;
import com.squareup.okhttp.internal.io.IoUtils;
import com.squareup.okhttp.internal.io.StrictLineReader;
import com.squareup.okhttp.internal.util.Charsets;
import com.squareup.okhttp.internal.util.ExtendedResponseCache;
import com.squareup.okhttp.ExtendedResponseCache;
import com.squareup.okhttp.internal.util.IntegralToString;
import com.squareup.okhttp.internal.util.ResponseSource;
import com.squareup.okhttp.ResponseSource;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;

View File

@@ -150,7 +150,7 @@ final class HttpTransport implements Transport {
}
private void receiveHeaders(RawHeaders headers) throws IOException {
CookieHandler cookieHandler = CookieHandler.getDefault();
CookieHandler cookieHandler = httpEngine.policy.cookieHandler;
if (cookieHandler != null) {
cookieHandler.put(httpEngine.uri, headers.toMultimap(true));
}

View File

@@ -23,11 +23,14 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.CookieHandler;
import java.net.HttpRetryException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.ResponseCache;
import java.net.SocketPermission;
import java.net.URL;
import java.security.Permission;
@@ -60,6 +63,9 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
private final int defaultPort;
private Proxy proxy;
final ProxySelector proxySelector;
final CookieHandler cookieHandler;
final ResponseCache responseCache;
private final RawHeaders rawRequestHeaders = new RawHeaders();
@@ -68,14 +74,14 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
protected IOException httpEngineFailure;
protected HttpEngine httpEngine;
public HttpURLConnectionImpl(URL url, int port) {
public HttpURLConnectionImpl(URL url, int defaultPort, Proxy proxy, ProxySelector proxySelector,
CookieHandler cookieHandler, ResponseCache responseCache) {
super(url);
defaultPort = port;
}
public HttpURLConnectionImpl(URL url, int port, Proxy proxy) {
this(url, port);
this.defaultPort = defaultPort;
this.proxy = proxy;
this.proxySelector = proxySelector;
this.cookieHandler = cookieHandler;
this.responseCache = responseCache;
}
@Override public final void connect() throws IOException {

View File

@@ -20,9 +20,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.CacheResponse;
import java.net.CookieHandler;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.ResponseCache;
import java.net.SecureCacheResponse;
import java.net.URL;
import java.security.Permission;
@@ -41,14 +44,11 @@ public final class HttpsURLConnectionImpl extends HttpsURLConnection {
/** HttpUrlConnectionDelegate allows reuse of HttpURLConnectionImpl. */
private final HttpUrlConnectionDelegate delegate;
public HttpsURLConnectionImpl(URL url, int port) {
public HttpsURLConnectionImpl(URL url, int defaultPort, Proxy proxy,
ProxySelector proxySelector, CookieHandler cookieHandler, ResponseCache responseCache) {
super(url);
delegate = new HttpUrlConnectionDelegate(url, port);
}
public HttpsURLConnectionImpl(URL url, int port, Proxy proxy) {
super(url);
delegate = new HttpUrlConnectionDelegate(url, port, proxy);
delegate = new HttpUrlConnectionDelegate(url, defaultPort, proxy, proxySelector,
cookieHandler, responseCache);
}
private void checkConnected() {
@@ -371,12 +371,10 @@ public final class HttpsURLConnectionImpl extends HttpsURLConnection {
}
private final class HttpUrlConnectionDelegate extends HttpURLConnectionImpl {
private HttpUrlConnectionDelegate(URL url, int port) {
super(url, port);
}
private HttpUrlConnectionDelegate(URL url, int port, Proxy proxy) {
super(url, port, proxy);
private HttpUrlConnectionDelegate(URL url, int defaultPort, Proxy proxy,
ProxySelector proxySelector, CookieHandler cookieHandler,
ResponseCache responseCache) {
super(url, defaultPort, proxy, proxySelector, cookieHandler, responseCache);
}
@Override protected HttpEngine newHttpEngine(String method, RawHeaders requestHeaders,

View File

@@ -17,7 +17,7 @@
package com.squareup.okhttp.internal.net.http;
import com.squareup.okhttp.internal.util.Objects;
import com.squareup.okhttp.internal.util.ResponseSource;
import com.squareup.okhttp.ResponseSource;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URI;

View File

@@ -83,10 +83,10 @@ public final class URLConnectionTest extends TestCase {
/** base64("username:password") */
private static final String BASE_64_CREDENTIALS = "dXNlcm5hbWU6cGFzc3dvcmQ=";
private ProxySelector defaultProxySelector = ProxySelector.getDefault();
private MockWebServer server = new MockWebServer();
private MockWebServer server2 = new MockWebServer();
private final OkHttpClient client = new OkHttpClient();
private HttpResponseCache cache;
private String hostName;
@@ -107,9 +107,6 @@ public final class URLConnectionTest extends TestCase {
}
@Override protected void tearDown() throws Exception {
ResponseCache.setDefault(null);
Authenticator.setDefault(null);
ProxySelector.setDefault(defaultProxySelector);
System.clearProperty("proxyHost");
System.clearProperty("proxyPort");
System.clearProperty("http.proxyHost");
@@ -124,12 +121,8 @@ public final class URLConnectionTest extends TestCase {
super.tearDown();
}
private static HttpURLConnection openConnection(URL url) {
return new OkHttpClient().open(url);
}
private static HttpURLConnection openConnection(URL url, Proxy proxy) {
return new OkHttpClient().setProxy(proxy).open(url);
private HttpURLConnection openConnection(URL url) {
return client.open(url);
}
// TODO: test that request bodies are retransmitted on IP address failures
@@ -322,7 +315,7 @@ public final class URLConnectionTest extends TestCase {
server2.play();
FakeProxySelector proxySelector = new FakeProxySelector();
proxySelector.proxies.add(server2.toProxyAddress());
ProxySelector.setDefault(proxySelector);
client.setProxySelector(proxySelector);
server2.shutdown();
HttpURLConnection connection = openConnection(server.getUrl("/def"));
@@ -626,7 +619,7 @@ public final class URLConnectionTest extends TestCase {
server.play();
URL url = new URL("http://android.com/foo");
HttpURLConnection connection = proxyConfig.connect(server, url);
HttpURLConnection connection = proxyConfig.connect(server, client, url);
assertContent("this response comes via a proxy", connection);
RecordedRequest request = server.takeRequest();
@@ -675,7 +668,7 @@ public final class URLConnectionTest extends TestCase {
server.play();
URL url = server.getUrl("/foo");
HttpsURLConnection connection = (HttpsURLConnection) proxyConfig.connect(server, url);
HttpsURLConnection connection = (HttpsURLConnection) proxyConfig.connect(server, client, url);
connection.setSSLSocketFactory(sslContext.getSocketFactory());
connection.setHostnameVerifier(new RecordingHostnameVerifier());
@@ -716,7 +709,7 @@ public final class URLConnectionTest extends TestCase {
server.play();
URL url = new URL("https://android.com/foo");
HttpsURLConnection connection = (HttpsURLConnection) proxyConfig.connect(server, url);
HttpsURLConnection connection = (HttpsURLConnection) proxyConfig.connect(server, client, url);
connection.setSSLSocketFactory(sslContext.getSocketFactory());
connection.setHostnameVerifier(hostnameVerifier);
@@ -752,10 +745,10 @@ public final class URLConnectionTest extends TestCase {
server.enqueue(response); // For the backwards-compatible SSLv3 retry
}
server.play();
client.setProxy(server.toProxyAddress());
URL url = new URL("https://android.com/foo");
HttpsURLConnection connection = (HttpsURLConnection) openConnection(
url, server.toProxyAddress());
HttpsURLConnection connection = (HttpsURLConnection) client.open(url);
connection.setSSLSocketFactory(sslContext.getSocketFactory());
try {
@@ -777,7 +770,7 @@ public final class URLConnectionTest extends TestCase {
String tmp = System.getProperty("java.io.tmpdir");
File cacheDir = new File(tmp, "HttpCache-" + UUID.randomUUID());
cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE);
ResponseCache.setDefault(cache);
client.setResponseCache(cache);
}
/**
@@ -793,10 +786,10 @@ public final class URLConnectionTest extends TestCase {
.clearHeaders());
server.enqueue(new MockResponse().setBody("encrypted response from the origin server"));
server.play();
client.setProxy(server.toProxyAddress());
URL url = new URL("https://android.com/foo");
HttpsURLConnection connection = (HttpsURLConnection) openConnection(
url, server.toProxyAddress());
HttpsURLConnection connection = (HttpsURLConnection) client.open(url);
connection.addRequestProperty("Private", "Secret");
connection.addRequestProperty("Proxy-Authorization", "bar");
connection.addRequestProperty("User-Agent", "baz");
@@ -827,10 +820,10 @@ public final class URLConnectionTest extends TestCase {
.clearHeaders());
server.enqueue(new MockResponse().setBody("A"));
server.play();
client.setProxy(server.toProxyAddress());
URL url = new URL("https://android.com/foo");
HttpsURLConnection connection = (HttpsURLConnection) openConnection(
url, server.toProxyAddress());
HttpsURLConnection connection = (HttpsURLConnection) client.open(url);
connection.setSSLSocketFactory(sslContext.getSocketFactory());
connection.setHostnameVerifier(new RecordingHostnameVerifier());
assertContent("A", connection);
@@ -857,10 +850,10 @@ public final class URLConnectionTest extends TestCase {
.clearHeaders());
server.enqueue(new MockResponse().setBody("this response comes via a proxy"));
server.play();
client.setProxy(server.toProxyAddress());
URL url = new URL("https://android.com/foo");
HttpsURLConnection connection = (HttpsURLConnection) openConnection(
url, server.toProxyAddress());
HttpsURLConnection connection = (HttpsURLConnection) client.open(url);
connection.setRequestProperty("Connection", "close");
connection.setSSLSocketFactory(sslContext.getSocketFactory());
connection.setHostnameVerifier(new RecordingHostnameVerifier());
@@ -879,16 +872,15 @@ public final class URLConnectionTest extends TestCase {
server.enqueue(new MockResponse().setBody("response 1"));
server.enqueue(new MockResponse().setBody("response 2"));
server.play();
client.setProxy(server.toProxyAddress());
URL url = new URL("https://android.com/foo");
HttpsURLConnection connection1 = (HttpsURLConnection) openConnection(
url, server.toProxyAddress());
HttpsURLConnection connection1 = (HttpsURLConnection) client.open(url);
connection1.setSSLSocketFactory(socketFactory);
connection1.setHostnameVerifier(hostnameVerifier);
assertContent("response 1", connection1);
HttpsURLConnection connection2 = (HttpsURLConnection) openConnection(
url, server.toProxyAddress());
HttpsURLConnection connection2 = (HttpsURLConnection) client.open(url);
connection2.setSSLSocketFactory(socketFactory);
connection2.setHostnameVerifier(hostnameVerifier);
assertContent("response 2", connection2);
@@ -1301,9 +1293,13 @@ public final class URLConnectionTest extends TestCase {
server.enqueue(pleaseAuthenticate);
server.play();
HttpURLConnection connection = proxy
? openConnection(new URL("http://android.com"), server.toProxyAddress())
: openConnection(server.getUrl("/"));
HttpURLConnection connection;
if (proxy) {
client.setProxy(server.toProxyAddress());
connection = client.open(new URL("http://android.com"));
} else {
connection = client.open(server.getUrl("/"));
}
assertEquals(responseCode, connection.getResponseCode());
return authenticator.calls;
}
@@ -2024,11 +2020,14 @@ public final class URLConnectionTest extends TestCase {
private URI backdoorUrlToUri(URL url) throws Exception {
final AtomicReference<URI> uriReference = new AtomicReference<URI>();
ResponseCache.setDefault(new ResponseCache() {
@Override public CacheRequest put(URI uri, URLConnection connection) throws IOException {
client.setResponseCache(new ResponseCache() {
@Override
public CacheRequest put(URI uri, URLConnection connection) throws IOException {
return null;
}
@Override public CacheResponse get(URI uri, String requestMethod,
@Override
public CacheResponse get(URI uri, String requestMethod,
Map<String, List<String>> requestHeaders) throws IOException {
uriReference.set(uri);
throw new UnsupportedOperationException();
@@ -2052,17 +2051,23 @@ public final class URLConnectionTest extends TestCase {
*/
public void testResponseCacheReturnsNullOutputStream() throws Exception {
final AtomicBoolean aborted = new AtomicBoolean();
ResponseCache.setDefault(new ResponseCache() {
@Override public CacheResponse get(URI uri, String requestMethod,
client.setResponseCache(new ResponseCache() {
@Override
public CacheResponse get(URI uri, String requestMethod,
Map<String, List<String>> requestHeaders) throws IOException {
return null;
}
@Override public CacheRequest put(URI uri, URLConnection connection) throws IOException {
@Override
public CacheRequest put(URI uri, URLConnection connection) throws IOException {
return new CacheRequest() {
@Override public void abort() {
@Override
public void abort() {
aborted.set(true);
}
@Override public OutputStream getBody() throws IOException {
@Override
public OutputStream getBody() throws IOException {
return null;
}
};
@@ -2337,47 +2342,49 @@ public final class URLConnectionTest extends TestCase {
enum ProxyConfig {
NO_PROXY() {
@Override public HttpURLConnection connect(MockWebServer server, URL url)
throws IOException {
return openConnection(url, Proxy.NO_PROXY);
@Override public HttpURLConnection connect
(MockWebServer server, OkHttpClient client, URL url) throws IOException {
client.setProxy(Proxy.NO_PROXY);
return client.open(url);
}
},
CREATE_ARG() {
@Override public HttpURLConnection connect(MockWebServer server, URL url)
throws IOException {
return openConnection(url, server.toProxyAddress());
@Override public HttpURLConnection connect(
MockWebServer server, OkHttpClient client, URL url) throws IOException {
client.setProxy(server.toProxyAddress());
return client.open(url);
}
},
PROXY_SYSTEM_PROPERTY() {
@Override public HttpURLConnection connect(MockWebServer server, URL url)
throws IOException {
@Override public HttpURLConnection connect(
MockWebServer server, OkHttpClient client, URL url) throws IOException {
System.setProperty("proxyHost", "localhost");
System.setProperty("proxyPort", Integer.toString(server.getPort()));
return openConnection(url);
return client.open(url);
}
},
HTTP_PROXY_SYSTEM_PROPERTY() {
@Override public HttpURLConnection connect(MockWebServer server, URL url)
throws IOException {
@Override public HttpURLConnection connect(
MockWebServer server, OkHttpClient client, URL url) throws IOException {
System.setProperty("http.proxyHost", "localhost");
System.setProperty("http.proxyPort", Integer.toString(server.getPort()));
return openConnection(url);
return client.open(url);
}
},
HTTPS_PROXY_SYSTEM_PROPERTY() {
@Override public HttpURLConnection connect(MockWebServer server, URL url)
throws IOException {
@Override public HttpURLConnection connect(
MockWebServer server, OkHttpClient client, URL url) throws IOException {
System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", Integer.toString(server.getPort()));
return openConnection(url);
return client.open(url);
}
};
public abstract HttpURLConnection connect(MockWebServer server, URL url) throws IOException;
public abstract HttpURLConnection connect(MockWebServer server, OkHttpClient client, URL url) throws IOException;
}
private static class RecordingTrustManager implements X509TrustManager {