• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 Square, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.squareup.okhttp;
17 
18 import com.squareup.okhttp.internal.Util;
19 import com.squareup.okhttp.internal.http.HttpAuthenticator;
20 import com.squareup.okhttp.internal.http.HttpURLConnectionImpl;
21 import com.squareup.okhttp.internal.http.HttpsURLConnectionImpl;
22 import com.squareup.okhttp.internal.http.ResponseCacheAdapter;
23 import com.squareup.okhttp.internal.tls.OkHostnameVerifier;
24 import java.io.IOException;
25 import java.net.CookieHandler;
26 import java.net.HttpURLConnection;
27 import java.net.Proxy;
28 import java.net.ProxySelector;
29 import java.net.ResponseCache;
30 import java.net.URL;
31 import java.net.URLConnection;
32 import java.net.URLStreamHandler;
33 import java.net.URLStreamHandlerFactory;
34 import java.security.GeneralSecurityException;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.concurrent.TimeUnit;
38 import javax.net.SocketFactory;
39 import javax.net.ssl.HostnameVerifier;
40 import javax.net.ssl.SSLContext;
41 import javax.net.ssl.SSLSocketFactory;
42 import okio.ByteString;
43 
44 /**
45  * Configures and creates HTTP connections. Most applications can use a single
46  * OkHttpClient for all of their HTTP requests - benefiting from a shared
47  * response cache, thread pool, connection re-use, etc.
48  *
49  * Instances of OkHttpClient are intended to be fully configured before they're
50  * shared - once shared they should be treated as immutable and can safely be used
51  * to concurrently open new connections. If required, threads can call
52  * {@link #clone()} to make a shallow copy of the OkHttpClient that can be
53  * safely modified with further configuration changes.
54  */
55 public final class OkHttpClient implements URLStreamHandlerFactory, Cloneable {
56 
57   private final RouteDatabase routeDatabase;
58   private Dispatcher dispatcher;
59   private Proxy proxy;
60   private List<Protocol> protocols;
61   private ProxySelector proxySelector;
62   private CookieHandler cookieHandler;
63   private OkResponseCache responseCache;
64   private SocketFactory socketFactory;
65   private SSLSocketFactory sslSocketFactory;
66   private HostnameVerifier hostnameVerifier;
67   private OkAuthenticator authenticator;
68   private ConnectionPool connectionPool;
69   private HostResolver hostResolver;
70   private boolean followProtocolRedirects = true;
71   private int connectTimeout;
72   private int readTimeout;
73 
OkHttpClient()74   public OkHttpClient() {
75     routeDatabase = new RouteDatabase();
76     dispatcher = new Dispatcher();
77   }
78 
79   /**
80    * Sets the default connect timeout for new connections. A value of 0 means no timeout.
81    *
82    * @see URLConnection#setConnectTimeout(int)
83    */
setConnectTimeout(long timeout, TimeUnit unit)84   public void setConnectTimeout(long timeout, TimeUnit unit) {
85     if (timeout < 0) {
86       throw new IllegalArgumentException("timeout < 0");
87     }
88     if (unit == null) {
89       throw new IllegalArgumentException("unit == null");
90     }
91     long millis = unit.toMillis(timeout);
92     if (millis > Integer.MAX_VALUE) {
93       throw new IllegalArgumentException("Timeout too large.");
94     }
95     connectTimeout = (int) millis;
96   }
97 
98   /** Default connect timeout (in milliseconds). */
getConnectTimeout()99   public int getConnectTimeout() {
100     return connectTimeout;
101   }
102 
103   /**
104    * Sets the default read timeout for new connections. A value of 0 means no timeout.
105    *
106    * @see URLConnection#setReadTimeout(int)
107    */
setReadTimeout(long timeout, TimeUnit unit)108   public void setReadTimeout(long timeout, TimeUnit unit) {
109     if (timeout < 0) {
110       throw new IllegalArgumentException("timeout < 0");
111     }
112     if (unit == null) {
113       throw new IllegalArgumentException("unit == null");
114     }
115     long millis = unit.toMillis(timeout);
116     if (millis > Integer.MAX_VALUE) {
117       throw new IllegalArgumentException("Timeout too large.");
118     }
119     readTimeout = (int) millis;
120   }
121 
122   /** Default read timeout (in milliseconds). */
getReadTimeout()123   public int getReadTimeout() {
124     return readTimeout;
125   }
126 
127   /**
128    * Sets the HTTP proxy that will be used by connections created by this
129    * client. This takes precedence over {@link #setProxySelector}, which is
130    * only honored when this proxy is null (which it is by default). To disable
131    * proxy use completely, call {@code setProxy(Proxy.NO_PROXY)}.
132    */
setProxy(Proxy proxy)133   public OkHttpClient setProxy(Proxy proxy) {
134     this.proxy = proxy;
135     return this;
136   }
137 
getProxy()138   public Proxy getProxy() {
139     return proxy;
140   }
141 
142   /**
143    * Sets the proxy selection policy to be used if no {@link #setProxy proxy}
144    * is specified explicitly. The proxy selector may return multiple proxies;
145    * in that case they will be tried in sequence until a successful connection
146    * is established.
147    *
148    * <p>If unset, the {@link ProxySelector#getDefault() system-wide default}
149    * proxy selector will be used.
150    */
setProxySelector(ProxySelector proxySelector)151   public OkHttpClient setProxySelector(ProxySelector proxySelector) {
152     this.proxySelector = proxySelector;
153     return this;
154   }
155 
getProxySelector()156   public ProxySelector getProxySelector() {
157     return proxySelector;
158   }
159 
160   /**
161    * Sets the cookie handler to be used to read outgoing cookies and write
162    * incoming cookies.
163    *
164    * <p>If unset, the {@link CookieHandler#getDefault() system-wide default}
165    * cookie handler will be used.
166    */
setCookieHandler(CookieHandler cookieHandler)167   public OkHttpClient setCookieHandler(CookieHandler cookieHandler) {
168     this.cookieHandler = cookieHandler;
169     return this;
170   }
171 
getCookieHandler()172   public CookieHandler getCookieHandler() {
173     return cookieHandler;
174   }
175 
176   /**
177    * Sets the response cache to be used to read and write cached responses.
178    */
setResponseCache(ResponseCache responseCache)179   public OkHttpClient setResponseCache(ResponseCache responseCache) {
180     return setOkResponseCache(toOkResponseCache(responseCache));
181   }
182 
getResponseCache()183   public ResponseCache getResponseCache() {
184     return responseCache instanceof ResponseCacheAdapter
185         ? ((ResponseCacheAdapter) responseCache).getDelegate()
186         : null;
187   }
188 
setOkResponseCache(OkResponseCache responseCache)189   public OkHttpClient setOkResponseCache(OkResponseCache responseCache) {
190     this.responseCache = responseCache;
191     return this;
192   }
193 
getOkResponseCache()194   public OkResponseCache getOkResponseCache() {
195     return responseCache;
196   }
197 
198   /**
199    * Sets the socket factory used to create connections.
200    *
201    * <p>If unset, the {@link SocketFactory#getDefault() system-wide default}
202    * socket factory will be used.
203    */
setSocketFactory(SocketFactory socketFactory)204   public OkHttpClient setSocketFactory(SocketFactory socketFactory) {
205     this.socketFactory = socketFactory;
206     return this;
207   }
208 
getSocketFactory()209   public SocketFactory getSocketFactory() {
210     return socketFactory;
211   }
212 
213   /**
214    * Sets the socket factory used to secure HTTPS connections.
215    *
216    * <p>If unset, a lazily created SSL socket factory will be used.
217    */
setSslSocketFactory(SSLSocketFactory sslSocketFactory)218   public OkHttpClient setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
219     this.sslSocketFactory = sslSocketFactory;
220     return this;
221   }
222 
getSslSocketFactory()223   public SSLSocketFactory getSslSocketFactory() {
224     return sslSocketFactory;
225   }
226 
227   /**
228    * Sets the verifier used to confirm that response certificates apply to
229    * requested hostnames for HTTPS connections.
230    *
231    * <p>If unset, the
232    * {@link javax.net.ssl.HttpsURLConnection#getDefaultHostnameVerifier()
233    * system-wide default} hostname verifier will be used.
234    */
setHostnameVerifier(HostnameVerifier hostnameVerifier)235   public OkHttpClient setHostnameVerifier(HostnameVerifier hostnameVerifier) {
236     this.hostnameVerifier = hostnameVerifier;
237     return this;
238   }
239 
getHostnameVerifier()240   public HostnameVerifier getHostnameVerifier() {
241     return hostnameVerifier;
242   }
243 
244   /**
245    * Sets the authenticator used to respond to challenges from the remote web
246    * server or proxy server.
247    *
248    * <p>If unset, the {@link java.net.Authenticator#setDefault system-wide default}
249    * authenticator will be used.
250    */
setAuthenticator(OkAuthenticator authenticator)251   public OkHttpClient setAuthenticator(OkAuthenticator authenticator) {
252     this.authenticator = authenticator;
253     return this;
254   }
255 
getAuthenticator()256   public OkAuthenticator getAuthenticator() {
257     return authenticator;
258   }
259 
260   /**
261    * Sets the connection pool used to recycle HTTP and HTTPS connections.
262    *
263    * <p>If unset, the {@link ConnectionPool#getDefault() system-wide
264    * default} connection pool will be used.
265    */
setConnectionPool(ConnectionPool connectionPool)266   public OkHttpClient setConnectionPool(ConnectionPool connectionPool) {
267     this.connectionPool = connectionPool;
268     return this;
269   }
270 
getConnectionPool()271   public ConnectionPool getConnectionPool() {
272     return connectionPool;
273   }
274 
275   /**
276    * Configure this client to follow redirects from HTTPS to HTTP and from HTTP
277    * to HTTPS.
278    *
279    * <p>If unset, protocol redirects will be followed. This is different than
280    * the built-in {@code HttpURLConnection}'s default.
281    */
setFollowProtocolRedirects(boolean followProtocolRedirects)282   public OkHttpClient setFollowProtocolRedirects(boolean followProtocolRedirects) {
283     this.followProtocolRedirects = followProtocolRedirects;
284     return this;
285   }
286 
getFollowProtocolRedirects()287   public boolean getFollowProtocolRedirects() {
288     return followProtocolRedirects;
289   }
290 
getRoutesDatabase()291   public RouteDatabase getRoutesDatabase() {
292     return routeDatabase;
293   }
294 
295   /**
296    * Sets the dispatcher used to set policy and execute asynchronous requests.
297    * Must not be null.
298    */
setDispatcher(Dispatcher dispatcher)299   public OkHttpClient setDispatcher(Dispatcher dispatcher) {
300     if (dispatcher == null) throw new IllegalArgumentException("dispatcher == null");
301     this.dispatcher = dispatcher;
302     return this;
303   }
304 
getDispatcher()305   public Dispatcher getDispatcher() {
306     return dispatcher;
307   }
308 
309   /**
310    * @deprecated OkHttp 1.5 enforces an enumeration of {@link Protocol
311    *     protocols} that can be selected. Please switch to {@link
312    *     #setProtocols(java.util.List)}.
313    */
314   @Deprecated
setTransports(List<String> transports)315   public OkHttpClient setTransports(List<String> transports) {
316     List<Protocol> protocols = new ArrayList<Protocol>(transports.size());
317     for (int i = 0, size = transports.size(); i < size; i++) {
318       try {
319         Protocol protocol = Protocol.find(ByteString.encodeUtf8(transports.get(i)));
320         protocols.add(protocol);
321       } catch (IOException e) {
322         throw new IllegalArgumentException(e);
323       }
324     }
325     return setProtocols(protocols);
326   }
327 
328   /**
329    * Configure the protocols used by this client to communicate with remote
330    * servers. By default this client will prefer the most efficient transport
331    * available, falling back to more ubiquitous protocols. Applications should
332    * only call this method to avoid specific compatibility problems, such as web
333    * servers that behave incorrectly when SPDY is enabled.
334    *
335    * <p>The following protocols are currently supported:
336    * <ul>
337    *   <li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">http/1.1</a>
338    *   <li><a href="http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1">spdy/3.1</a>
339    *   <li><a href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-09">HTTP-draft-09/2.0</a>
340    * </ul>
341    *
342    * <p><strong>This is an evolving set.</strong> Future releases may drop
343    * support for transitional protocols (like spdy/3.1), in favor of their
344    * successors (spdy/4 or http/2.0). The http/1.1 transport will never be
345    * dropped.
346    *
347    * <p>If multiple protocols are specified, <a
348    * href="https://technotes.googlecode.com/git/nextprotoneg.html">NPN</a> will
349    * be used to negotiate a transport. Future releases may use another mechanism
350    * (such as <a href="http://tools.ietf.org/html/draft-friedl-tls-applayerprotoneg-02">ALPN</a>)
351    * to negotiate a transport.
352    *
353    * @param protocols the protocols to use, in order of preference. The list
354    *     must contain "http/1.1". It must not contain null.
355    */
setProtocols(List<Protocol> protocols)356   public OkHttpClient setProtocols(List<Protocol> protocols) {
357     protocols = Util.immutableList(protocols);
358     if (!protocols.contains(Protocol.HTTP_11)) {
359       throw new IllegalArgumentException("protocols doesn't contain http/1.1: " + protocols);
360     }
361     if (protocols.contains(null)) {
362       throw new IllegalArgumentException("protocols must not contain null");
363     }
364     this.protocols = Util.immutableList(protocols);
365     return this;
366   }
367 
368   /**
369    * @deprecated OkHttp 1.5 enforces an enumeration of {@link Protocol
370    *     protocols} that can be selected. Please switch to {@link
371    *     #getProtocols()}.
372    */
373   @Deprecated
getTransports()374   public List<String> getTransports() {
375     List<String> transports = new ArrayList<String>(protocols.size());
376     for (int i = 0, size = protocols.size(); i < size; i++) {
377       transports.add(protocols.get(i).name.utf8());
378     }
379     return transports;
380   }
381 
getProtocols()382   public List<Protocol> getProtocols() {
383     return protocols;
384   }
385 
386   /*
387    * Sets the {@code HostResolver} that will be used by this client to resolve
388    * hostnames to IP addresses.
389    */
setHostResolver(HostResolver hostResolver)390   public OkHttpClient setHostResolver(HostResolver hostResolver) {
391     this.hostResolver = hostResolver;
392     return this;
393   }
394 
getHostResolver()395   public HostResolver getHostResolver() {
396     return hostResolver;
397   }
398 
399   /**
400    * Invokes {@code request} immediately, and blocks until the response can be
401    * processed or is in error.
402    *
403    * <p>The caller may read the response body with the response's
404    * {@link Response#body} method.  To facilitate connection recycling, callers
405    * should always {@link Response.Body#close() close the response body}.
406    *
407    * <p>Note that transport-layer success (receiving a HTTP response code,
408    * headers and body) does not necessarily indicate application-layer
409    * success: {@code response} may still indicate an unhappy HTTP response
410    * code like 404 or 500.
411    *
412    * <h3>Non-blocking responses</h3>
413    *
414    * <p>Receivers do not need to block while waiting for the response body to
415    * download. Instead, they can get called back as data arrives. Use {@link
416    * Response.Body#ready} to check if bytes should be read immediately. While
417    * there is data ready, read it.
418    *
419    * <p>The current implementation of {@link Response.Body#ready} always
420    * returns true when the underlying transport is HTTP/1. This results in
421    * blocking on that transport. For effective non-blocking your server must
422    * support {@link Protocol#SPDY_3} or {@link Protocol#HTTP_2}.
423    *
424    * @throws IOException when the request could not be executed due to a
425    * connectivity problem or timeout. Because networks can fail during an
426    * exchange, it is possible that the remote server accepted the request
427    * before the failure.
428    */
execute(Request request)429   public Response execute(Request request) throws IOException {
430     // Copy the client. Otherwise changes (socket factory, redirect policy,
431     // etc.) may incorrectly be reflected in the request when it is executed.
432     OkHttpClient client = copyWithDefaults();
433     Job job = new Job(dispatcher, client, request, null);
434     Response result = job.getResponse(); // Since we don't cancel, this won't be null.
435     job.engine.releaseConnection(); // Transfer ownership of the body to the caller.
436     return result;
437   }
438 
439   /**
440    * Schedules {@code request} to be executed at some point in the future. The
441    * {@link #getDispatcher dispatcher} defines when the request will run:
442    * usually immediately unless there are several other requests currently being
443    * executed.
444    *
445    * <p>This client will later call back {@code responseReceiver} with either an
446    * HTTP response or a failure exception. If you {@link #cancel} a request
447    * before it completes the receiver will not be called back.
448    */
enqueue(Request request, Response.Receiver responseReceiver)449   public void enqueue(Request request, Response.Receiver responseReceiver) {
450     dispatcher.enqueue(this, request, responseReceiver);
451   }
452 
453   /**
454    * Cancels all scheduled tasks tagged with {@code tag}. Requests that are already
455    * complete cannot be canceled.
456    */
cancel(Object tag)457   public void cancel(Object tag) {
458     dispatcher.cancel(tag);
459   }
460 
open(URL url)461   public HttpURLConnection open(URL url) {
462     return open(url, proxy);
463   }
464 
open(URL url, Proxy proxy)465   HttpURLConnection open(URL url, Proxy proxy) {
466     String protocol = url.getProtocol();
467     OkHttpClient copy = copyWithDefaults();
468     copy.proxy = proxy;
469 
470     if (protocol.equals("http")) return new HttpURLConnectionImpl(url, copy);
471     if (protocol.equals("https")) return new HttpsURLConnectionImpl(url, copy);
472     throw new IllegalArgumentException("Unexpected protocol: " + protocol);
473   }
474 
475   /**
476    * Returns a shallow copy of this OkHttpClient that uses the system-wide
477    * default for each field that hasn't been explicitly configured.
478    */
copyWithDefaults()479   OkHttpClient copyWithDefaults() {
480     OkHttpClient result = clone();
481     if (result.proxySelector == null) {
482       result.proxySelector = ProxySelector.getDefault();
483     }
484     if (result.cookieHandler == null) {
485       result.cookieHandler = CookieHandler.getDefault();
486     }
487     if (result.responseCache == null) {
488       result.responseCache = toOkResponseCache(ResponseCache.getDefault());
489     }
490     if (result.socketFactory == null) {
491       result.socketFactory = SocketFactory.getDefault();
492     }
493     if (result.sslSocketFactory == null) {
494       result.sslSocketFactory = getDefaultSSLSocketFactory();
495     }
496     if (result.hostnameVerifier == null) {
497       result.hostnameVerifier = OkHostnameVerifier.INSTANCE;
498     }
499     if (result.authenticator == null) {
500       result.authenticator = HttpAuthenticator.SYSTEM_DEFAULT;
501     }
502     if (result.connectionPool == null) {
503       result.connectionPool = ConnectionPool.getDefault();
504     }
505     if (result.protocols == null) {
506       result.protocols = Protocol.HTTP2_SPDY3_AND_HTTP;
507     }
508     if (result.hostResolver == null) {
509       result.hostResolver = HostResolver.DEFAULT;
510     }
511     return result;
512   }
513 
514   /**
515    * Java and Android programs default to using a single global SSL context,
516    * accessible to HTTP clients as {@link SSLSocketFactory#getDefault()}. If we
517    * used the shared SSL context, when OkHttp enables NPN for its SPDY-related
518    * stuff, it would also enable NPN for other usages, which might crash them
519    * because NPN is enabled when it isn't expected to be.
520    * <p>
521    * This code avoids that by defaulting to an OkHttp created SSL context. The
522    * significant drawback of this approach is that apps that customize the
523    * global SSL context will lose these customizations.
524    */
getDefaultSSLSocketFactory()525   private synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
526     if (sslSocketFactory == null) {
527       try {
528         SSLContext sslContext = SSLContext.getInstance("TLS");
529         sslContext.init(null, null, null);
530         sslSocketFactory = sslContext.getSocketFactory();
531       } catch (GeneralSecurityException e) {
532         throw new AssertionError(); // The system has no TLS. Just give up.
533       }
534     }
535     return sslSocketFactory;
536   }
537 
538   /** Returns a shallow copy of this OkHttpClient. */
clone()539   @Override public OkHttpClient clone() {
540     try {
541       return (OkHttpClient) super.clone();
542     } catch (CloneNotSupportedException e) {
543       throw new AssertionError();
544     }
545   }
546 
toOkResponseCache(ResponseCache responseCache)547   private OkResponseCache toOkResponseCache(ResponseCache responseCache) {
548     return responseCache == null || responseCache instanceof OkResponseCache
549         ? (OkResponseCache) responseCache
550         : new ResponseCacheAdapter(responseCache);
551   }
552 
553   /**
554    * Creates a URLStreamHandler as a {@link URL#setURLStreamHandlerFactory}.
555    *
556    * <p>This code configures OkHttp to handle all HTTP and HTTPS connections
557    * created with {@link URL#openConnection()}: <pre>   {@code
558    *
559    *   OkHttpClient okHttpClient = new OkHttpClient();
560    *   URL.setURLStreamHandlerFactory(okHttpClient);
561    * }</pre>
562    */
createURLStreamHandler(final String protocol)563   public URLStreamHandler createURLStreamHandler(final String protocol) {
564     if (!protocol.equals("http") && !protocol.equals("https")) return null;
565 
566     return new URLStreamHandler() {
567       @Override protected URLConnection openConnection(URL url) {
568         return open(url);
569       }
570 
571       @Override protected URLConnection openConnection(URL url, Proxy proxy) {
572         return open(url, proxy);
573       }
574 
575       @Override protected int getDefaultPort() {
576         if (protocol.equals("http")) return 80;
577         if (protocol.equals("https")) return 443;
578         throw new AssertionError();
579       }
580     };
581   }
582 }
583