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.Internal; 19 import com.squareup.okhttp.internal.InternalCache; 20 import com.squareup.okhttp.internal.RouteDatabase; 21 import com.squareup.okhttp.internal.Util; 22 import com.squareup.okhttp.internal.http.AuthenticatorAdapter; 23 import com.squareup.okhttp.internal.http.StreamAllocation; 24 import com.squareup.okhttp.internal.io.RealConnection; 25 import com.squareup.okhttp.internal.tls.OkHostnameVerifier; 26 import java.net.CookieHandler; 27 import java.net.MalformedURLException; 28 import java.net.Proxy; 29 import java.net.ProxySelector; 30 import java.net.URLConnection; 31 import java.net.UnknownHostException; 32 import java.security.GeneralSecurityException; 33 import java.util.ArrayList; 34 import java.util.List; 35 import java.util.concurrent.TimeUnit; 36 import javax.net.SocketFactory; 37 import javax.net.ssl.HostnameVerifier; 38 import javax.net.ssl.SSLContext; 39 import javax.net.ssl.SSLSocket; 40 import javax.net.ssl.SSLSocketFactory; 41 42 /** 43 * Configures and creates HTTP connections. Most applications can use a single 44 * OkHttpClient for all of their HTTP requests - benefiting from a shared 45 * response cache, thread pool, connection re-use, etc. 46 * 47 * <p>Instances of OkHttpClient are intended to be fully configured before they're 48 * shared - once shared they should be treated as immutable and can safely be used 49 * to concurrently open new connections. If required, threads can call 50 * {@link #clone()} to make a shallow copy of the OkHttpClient that can be 51 * safely modified with further configuration changes. 52 */ 53 public class OkHttpClient implements Cloneable { 54 private static final List<Protocol> DEFAULT_PROTOCOLS = Util.immutableList( 55 Protocol.HTTP_2, Protocol.SPDY_3, Protocol.HTTP_1_1); 56 57 private static final List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList( 58 ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT); 59 60 static { 61 Internal.instance = new Internal() { 62 @Override public void addLenient(Headers.Builder builder, String line) { 63 builder.addLenient(line); 64 } 65 66 @Override public void addLenient(Headers.Builder builder, String name, String value) { 67 builder.addLenient(name, value); 68 } 69 70 @Override public void setCache(OkHttpClient client, InternalCache internalCache) { 71 client.setInternalCache(internalCache); 72 } 73 74 @Override public InternalCache internalCache(OkHttpClient client) { 75 return client.internalCache(); 76 } 77 78 @Override public boolean connectionBecameIdle( 79 ConnectionPool pool, RealConnection connection) { 80 return pool.connectionBecameIdle(connection); 81 } 82 83 @Override public RealConnection get( 84 ConnectionPool pool, Address address, StreamAllocation streamAllocation) { 85 return pool.get(address, streamAllocation); 86 } 87 88 @Override public void put(ConnectionPool pool, RealConnection connection) { 89 pool.put(connection); 90 } 91 92 @Override public RouteDatabase routeDatabase(ConnectionPool connectionPool) { 93 return connectionPool.routeDatabase; 94 } 95 96 @Override 97 public void callEnqueue(Call call, Callback responseCallback, boolean forWebSocket) { 98 call.enqueue(responseCallback, forWebSocket); 99 } 100 101 @Override public StreamAllocation callEngineGetStreamAllocation(Call call) { 102 return call.engine.streamAllocation; 103 } 104 105 @Override 106 public void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket, boolean isFallback) { 107 tlsConfiguration.apply(sslSocket, isFallback); 108 } 109 110 @Override public HttpUrl getHttpUrlChecked(String url) 111 throws MalformedURLException, UnknownHostException { 112 return HttpUrl.getChecked(url); 113 } 114 }; 115 } 116 117 /** Lazily-initialized. */ 118 private static SSLSocketFactory defaultSslSocketFactory; 119 120 private final RouteDatabase routeDatabase; 121 private Dispatcher dispatcher; 122 private Proxy proxy; 123 private List<Protocol> protocols; 124 private List<ConnectionSpec> connectionSpecs; 125 private final List<Interceptor> interceptors = new ArrayList<>(); 126 private final List<Interceptor> networkInterceptors = new ArrayList<>(); 127 private ProxySelector proxySelector; 128 private CookieHandler cookieHandler; 129 130 /** Non-null if this client is caching; possibly by {@code cache}. */ 131 private InternalCache internalCache; 132 private Cache cache; 133 134 private SocketFactory socketFactory; 135 private SSLSocketFactory sslSocketFactory; 136 private HostnameVerifier hostnameVerifier; 137 private CertificatePinner certificatePinner; 138 private Authenticator authenticator; 139 private ConnectionPool connectionPool; 140 private Dns dns; 141 private boolean followSslRedirects = true; 142 private boolean followRedirects = true; 143 private boolean retryOnConnectionFailure = true; 144 private int connectTimeout = 10_000; 145 private int readTimeout = 10_000; 146 private int writeTimeout = 10_000; 147 OkHttpClient()148 public OkHttpClient() { 149 routeDatabase = new RouteDatabase(); 150 dispatcher = new Dispatcher(); 151 } 152 OkHttpClient(OkHttpClient okHttpClient)153 private OkHttpClient(OkHttpClient okHttpClient) { 154 this.routeDatabase = okHttpClient.routeDatabase; 155 this.dispatcher = okHttpClient.dispatcher; 156 this.proxy = okHttpClient.proxy; 157 this.protocols = okHttpClient.protocols; 158 this.connectionSpecs = okHttpClient.connectionSpecs; 159 this.interceptors.addAll(okHttpClient.interceptors); 160 this.networkInterceptors.addAll(okHttpClient.networkInterceptors); 161 this.proxySelector = okHttpClient.proxySelector; 162 this.cookieHandler = okHttpClient.cookieHandler; 163 this.cache = okHttpClient.cache; 164 this.internalCache = cache != null ? cache.internalCache : okHttpClient.internalCache; 165 this.socketFactory = okHttpClient.socketFactory; 166 this.sslSocketFactory = okHttpClient.sslSocketFactory; 167 this.hostnameVerifier = okHttpClient.hostnameVerifier; 168 this.certificatePinner = okHttpClient.certificatePinner; 169 this.authenticator = okHttpClient.authenticator; 170 this.connectionPool = okHttpClient.connectionPool; 171 this.dns = okHttpClient.dns; 172 this.followSslRedirects = okHttpClient.followSslRedirects; 173 this.followRedirects = okHttpClient.followRedirects; 174 this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure; 175 this.connectTimeout = okHttpClient.connectTimeout; 176 this.readTimeout = okHttpClient.readTimeout; 177 this.writeTimeout = okHttpClient.writeTimeout; 178 } 179 180 /** 181 * Sets the default connect timeout for new connections. A value of 0 means no timeout, otherwise 182 * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds. 183 * 184 * @see URLConnection#setConnectTimeout(int) 185 */ setConnectTimeout(long timeout, TimeUnit unit)186 public void setConnectTimeout(long timeout, TimeUnit unit) { 187 if (timeout < 0) throw new IllegalArgumentException("timeout < 0"); 188 if (unit == null) throw new IllegalArgumentException("unit == null"); 189 long millis = unit.toMillis(timeout); 190 if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large."); 191 if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small."); 192 connectTimeout = (int) millis; 193 } 194 195 /** Default connect timeout (in milliseconds). */ getConnectTimeout()196 public int getConnectTimeout() { 197 return connectTimeout; 198 } 199 200 /** 201 * Sets the default read timeout for new connections. A value of 0 means no timeout, otherwise 202 * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds. 203 * 204 * @see URLConnection#setReadTimeout(int) 205 */ setReadTimeout(long timeout, TimeUnit unit)206 public void setReadTimeout(long timeout, TimeUnit unit) { 207 if (timeout < 0) throw new IllegalArgumentException("timeout < 0"); 208 if (unit == null) throw new IllegalArgumentException("unit == null"); 209 long millis = unit.toMillis(timeout); 210 if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large."); 211 if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small."); 212 readTimeout = (int) millis; 213 } 214 215 /** Default read timeout (in milliseconds). */ getReadTimeout()216 public int getReadTimeout() { 217 return readTimeout; 218 } 219 220 /** 221 * Sets the default write timeout for new connections. A value of 0 means no timeout, otherwise 222 * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds. 223 */ setWriteTimeout(long timeout, TimeUnit unit)224 public void setWriteTimeout(long timeout, TimeUnit unit) { 225 if (timeout < 0) throw new IllegalArgumentException("timeout < 0"); 226 if (unit == null) throw new IllegalArgumentException("unit == null"); 227 long millis = unit.toMillis(timeout); 228 if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large."); 229 if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small."); 230 writeTimeout = (int) millis; 231 } 232 233 /** Default write timeout (in milliseconds). */ getWriteTimeout()234 public int getWriteTimeout() { 235 return writeTimeout; 236 } 237 238 /** 239 * Sets the HTTP proxy that will be used by connections created by this 240 * client. This takes precedence over {@link #setProxySelector}, which is 241 * only honored when this proxy is null (which it is by default). To disable 242 * proxy use completely, call {@code setProxy(Proxy.NO_PROXY)}. 243 */ setProxy(Proxy proxy)244 public OkHttpClient setProxy(Proxy proxy) { 245 this.proxy = proxy; 246 return this; 247 } 248 getProxy()249 public Proxy getProxy() { 250 return proxy; 251 } 252 253 /** 254 * Sets the proxy selection policy to be used if no {@link #setProxy proxy} 255 * is specified explicitly. The proxy selector may return multiple proxies; 256 * in that case they will be tried in sequence until a successful connection 257 * is established. 258 * 259 * <p>If unset, the {@link ProxySelector#getDefault() system-wide default} 260 * proxy selector will be used. 261 */ setProxySelector(ProxySelector proxySelector)262 public OkHttpClient setProxySelector(ProxySelector proxySelector) { 263 this.proxySelector = proxySelector; 264 return this; 265 } 266 getProxySelector()267 public ProxySelector getProxySelector() { 268 return proxySelector; 269 } 270 271 /** 272 * Sets the cookie handler to be used to read outgoing cookies and write 273 * incoming cookies. 274 * 275 * <p>If unset, the {@link CookieHandler#getDefault() system-wide default} 276 * cookie handler will be used. 277 */ setCookieHandler(CookieHandler cookieHandler)278 public OkHttpClient setCookieHandler(CookieHandler cookieHandler) { 279 this.cookieHandler = cookieHandler; 280 return this; 281 } 282 getCookieHandler()283 public CookieHandler getCookieHandler() { 284 return cookieHandler; 285 } 286 287 /** Sets the response cache to be used to read and write cached responses. */ setInternalCache(InternalCache internalCache)288 void setInternalCache(InternalCache internalCache) { 289 this.internalCache = internalCache; 290 this.cache = null; 291 } 292 internalCache()293 InternalCache internalCache() { 294 return internalCache; 295 } 296 setCache(Cache cache)297 public OkHttpClient setCache(Cache cache) { 298 this.cache = cache; 299 this.internalCache = null; 300 return this; 301 } 302 getCache()303 public Cache getCache() { 304 return cache; 305 } 306 307 /** 308 * Sets the DNS service used to lookup IP addresses for hostnames. 309 * 310 * <p>If unset, the {@link Dns#SYSTEM system-wide default} DNS will be used. 311 */ setDns(Dns dns)312 public OkHttpClient setDns(Dns dns) { 313 this.dns = dns; 314 return this; 315 } 316 getDns()317 public Dns getDns() { 318 return dns; 319 } 320 321 /** 322 * Sets the socket factory used to create connections. OkHttp only uses 323 * the parameterless {@link SocketFactory#createSocket() createSocket()} 324 * method to create unconnected sockets. Overriding this method, 325 * e. g., allows the socket to be bound to a specific local address. 326 * 327 * <p>If unset, the {@link SocketFactory#getDefault() system-wide default} 328 * socket factory will be used. 329 */ setSocketFactory(SocketFactory socketFactory)330 public OkHttpClient setSocketFactory(SocketFactory socketFactory) { 331 this.socketFactory = socketFactory; 332 return this; 333 } 334 getSocketFactory()335 public SocketFactory getSocketFactory() { 336 return socketFactory; 337 } 338 339 /** 340 * Sets the socket factory used to secure HTTPS connections. 341 * 342 * <p>If unset, a lazily created SSL socket factory will be used. 343 */ setSslSocketFactory(SSLSocketFactory sslSocketFactory)344 public OkHttpClient setSslSocketFactory(SSLSocketFactory sslSocketFactory) { 345 this.sslSocketFactory = sslSocketFactory; 346 return this; 347 } 348 getSslSocketFactory()349 public SSLSocketFactory getSslSocketFactory() { 350 return sslSocketFactory; 351 } 352 353 /** 354 * Sets the verifier used to confirm that response certificates apply to 355 * requested hostnames for HTTPS connections. 356 * 357 * <p>If unset, a default hostname verifier will be used. 358 */ setHostnameVerifier(HostnameVerifier hostnameVerifier)359 public OkHttpClient setHostnameVerifier(HostnameVerifier hostnameVerifier) { 360 this.hostnameVerifier = hostnameVerifier; 361 return this; 362 } 363 getHostnameVerifier()364 public HostnameVerifier getHostnameVerifier() { 365 return hostnameVerifier; 366 } 367 368 /** 369 * Sets the certificate pinner that constrains which certificates are trusted. 370 * By default HTTPS connections rely on only the {@link #setSslSocketFactory 371 * SSL socket factory} to establish trust. Pinning certificates avoids the 372 * need to trust certificate authorities. 373 */ setCertificatePinner(CertificatePinner certificatePinner)374 public OkHttpClient setCertificatePinner(CertificatePinner certificatePinner) { 375 this.certificatePinner = certificatePinner; 376 return this; 377 } 378 getCertificatePinner()379 public CertificatePinner getCertificatePinner() { 380 return certificatePinner; 381 } 382 383 /** 384 * Sets the authenticator used to respond to challenges from the remote web 385 * server or proxy server. 386 * 387 * <p>If unset, the {@link java.net.Authenticator#setDefault system-wide default} 388 * authenticator will be used. 389 */ setAuthenticator(Authenticator authenticator)390 public OkHttpClient setAuthenticator(Authenticator authenticator) { 391 this.authenticator = authenticator; 392 return this; 393 } 394 getAuthenticator()395 public Authenticator getAuthenticator() { 396 return authenticator; 397 } 398 399 /** 400 * Sets the connection pool used to recycle HTTP and HTTPS connections. 401 * 402 * <p>If unset, the {@link ConnectionPool#getDefault() system-wide 403 * default} connection pool will be used. 404 */ setConnectionPool(ConnectionPool connectionPool)405 public OkHttpClient setConnectionPool(ConnectionPool connectionPool) { 406 this.connectionPool = connectionPool; 407 return this; 408 } 409 getConnectionPool()410 public ConnectionPool getConnectionPool() { 411 return connectionPool; 412 } 413 414 /** 415 * Configure this client to follow redirects from HTTPS to HTTP and from HTTP 416 * to HTTPS. 417 * 418 * <p>If unset, protocol redirects will be followed. This is different than 419 * the built-in {@code HttpURLConnection}'s default. 420 */ setFollowSslRedirects(boolean followProtocolRedirects)421 public OkHttpClient setFollowSslRedirects(boolean followProtocolRedirects) { 422 this.followSslRedirects = followProtocolRedirects; 423 return this; 424 } 425 getFollowSslRedirects()426 public boolean getFollowSslRedirects() { 427 return followSslRedirects; 428 } 429 430 /** Configure this client to follow redirects. If unset, redirects be followed. */ setFollowRedirects(boolean followRedirects)431 public void setFollowRedirects(boolean followRedirects) { 432 this.followRedirects = followRedirects; 433 } 434 getFollowRedirects()435 public boolean getFollowRedirects() { 436 return followRedirects; 437 } 438 439 /** 440 * Configure this client to retry or not when a connectivity problem is encountered. By default, 441 * this client silently recovers from the following problems: 442 * 443 * <ul> 444 * <li><strong>Unreachable IP addresses.</strong> If the URL's host has multiple IP addresses, 445 * failure to reach any individual IP address doesn't fail the overall request. This can 446 * increase availability of multi-homed services. 447 * <li><strong>Stale pooled connections.</strong> The {@link ConnectionPool} reuses sockets 448 * to decrease request latency, but these connections will occasionally time out. 449 * <li><strong>Unreachable proxy servers.</strong> A {@link ProxySelector} can be used to 450 * attempt multiple proxy servers in sequence, eventually falling back to a direct 451 * connection. 452 * </ul> 453 * 454 * Set this to false to avoid retrying requests when doing so is destructive. In this case the 455 * calling application should do its own recovery of connectivity failures. 456 */ setRetryOnConnectionFailure(boolean retryOnConnectionFailure)457 public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) { 458 this.retryOnConnectionFailure = retryOnConnectionFailure; 459 } 460 getRetryOnConnectionFailure()461 public boolean getRetryOnConnectionFailure() { 462 return retryOnConnectionFailure; 463 } 464 routeDatabase()465 RouteDatabase routeDatabase() { 466 return routeDatabase; 467 } 468 469 /** 470 * Sets the dispatcher used to set policy and execute asynchronous requests. 471 * Must not be null. 472 */ setDispatcher(Dispatcher dispatcher)473 public OkHttpClient setDispatcher(Dispatcher dispatcher) { 474 if (dispatcher == null) throw new IllegalArgumentException("dispatcher == null"); 475 this.dispatcher = dispatcher; 476 return this; 477 } 478 getDispatcher()479 public Dispatcher getDispatcher() { 480 return dispatcher; 481 } 482 483 /** 484 * Configure the protocols used by this client to communicate with remote 485 * servers. By default this client will prefer the most efficient transport 486 * available, falling back to more ubiquitous protocols. Applications should 487 * only call this method to avoid specific compatibility problems, such as web 488 * servers that behave incorrectly when SPDY is enabled. 489 * 490 * <p>The following protocols are currently supported: 491 * <ul> 492 * <li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">http/1.1</a> 493 * <li><a href="http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1">spdy/3.1</a> 494 * <li><a href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-17">h2</a> 495 * </ul> 496 * 497 * <p><strong>This is an evolving set.</strong> Future releases include 498 * support for transitional protocols. The http/1.1 transport will never be 499 * dropped. 500 * 501 * <p>If multiple protocols are specified, <a 502 * href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg">ALPN</a> 503 * will be used to negotiate a transport. 504 * 505 * <p>{@link Protocol#HTTP_1_0} is not supported in this set. Requests are 506 * initiated with {@code HTTP/1.1} only. If the server responds with {@code 507 * HTTP/1.0}, that will be exposed by {@link Response#protocol()}. 508 * 509 * @param protocols the protocols to use, in order of preference. The list 510 * must contain {@link Protocol#HTTP_1_1}. It must not contain null or 511 * {@link Protocol#HTTP_1_0}. 512 */ setProtocols(List<Protocol> protocols)513 public OkHttpClient setProtocols(List<Protocol> protocols) { 514 protocols = Util.immutableList(protocols); 515 if (!protocols.contains(Protocol.HTTP_1_1)) { 516 throw new IllegalArgumentException("protocols doesn't contain http/1.1: " + protocols); 517 } 518 if (protocols.contains(Protocol.HTTP_1_0)) { 519 throw new IllegalArgumentException("protocols must not contain http/1.0: " + protocols); 520 } 521 if (protocols.contains(null)) { 522 throw new IllegalArgumentException("protocols must not contain null"); 523 } 524 this.protocols = Util.immutableList(protocols); 525 return this; 526 } 527 getProtocols()528 public List<Protocol> getProtocols() { 529 return protocols; 530 } 531 setConnectionSpecs(List<ConnectionSpec> connectionSpecs)532 public OkHttpClient setConnectionSpecs(List<ConnectionSpec> connectionSpecs) { 533 this.connectionSpecs = Util.immutableList(connectionSpecs); 534 return this; 535 } 536 getConnectionSpecs()537 public List<ConnectionSpec> getConnectionSpecs() { 538 return connectionSpecs; 539 } 540 541 /** 542 * Returns a modifiable list of interceptors that observe the full span of each call: from before 543 * the connection is established (if any) until after the response source is selected (either the 544 * origin server, cache, or both). 545 */ interceptors()546 public List<Interceptor> interceptors() { 547 return interceptors; 548 } 549 550 /** 551 * Returns a modifiable list of interceptors that observe a single network request and response. 552 * These interceptors must call {@link Interceptor.Chain#proceed} exactly once: it is an error for 553 * a network interceptor to short-circuit or repeat a network request. 554 */ networkInterceptors()555 public List<Interceptor> networkInterceptors() { 556 return networkInterceptors; 557 } 558 559 /** 560 * Prepares the {@code request} to be executed at some point in the future. 561 */ newCall(Request request)562 public Call newCall(Request request) { 563 return new Call(this, request); 564 } 565 566 /** 567 * Cancels all scheduled or in-flight calls tagged with {@code tag}. Requests 568 * that are already complete cannot be canceled. 569 */ cancel(Object tag)570 public OkHttpClient cancel(Object tag) { 571 getDispatcher().cancel(tag); 572 return this; 573 } 574 575 /** 576 * Returns a shallow copy of this OkHttpClient that uses the system-wide 577 * default for each field that hasn't been explicitly configured. 578 */ copyWithDefaults()579 OkHttpClient copyWithDefaults() { 580 OkHttpClient result = new OkHttpClient(this); 581 if (result.proxySelector == null) { 582 result.proxySelector = ProxySelector.getDefault(); 583 } 584 if (result.cookieHandler == null) { 585 result.cookieHandler = CookieHandler.getDefault(); 586 } 587 if (result.socketFactory == null) { 588 result.socketFactory = SocketFactory.getDefault(); 589 } 590 if (result.sslSocketFactory == null) { 591 result.sslSocketFactory = getDefaultSSLSocketFactory(); 592 } 593 if (result.hostnameVerifier == null) { 594 result.hostnameVerifier = OkHostnameVerifier.INSTANCE; 595 } 596 if (result.certificatePinner == null) { 597 result.certificatePinner = CertificatePinner.DEFAULT; 598 } 599 if (result.authenticator == null) { 600 result.authenticator = AuthenticatorAdapter.INSTANCE; 601 } 602 if (result.connectionPool == null) { 603 result.connectionPool = ConnectionPool.getDefault(); 604 } 605 if (result.protocols == null) { 606 result.protocols = DEFAULT_PROTOCOLS; 607 } 608 if (result.connectionSpecs == null) { 609 result.connectionSpecs = DEFAULT_CONNECTION_SPECS; 610 } 611 if (result.dns == null) { 612 result.dns = Dns.SYSTEM; 613 } 614 return result; 615 } 616 617 /** 618 * Java and Android programs default to using a single global SSL context, 619 * accessible to HTTP clients as {@link SSLSocketFactory#getDefault()}. If we 620 * used the shared SSL context, when OkHttp enables ALPN for its SPDY-related 621 * stuff, it would also enable ALPN for other usages, which might crash them 622 * because ALPN is enabled when it isn't expected to be. 623 * 624 * <p>This code avoids that by defaulting to an OkHttp-created SSL context. 625 * The drawback of this approach is that apps that customize the global SSL 626 * context will lose these customizations. 627 */ getDefaultSSLSocketFactory()628 private synchronized SSLSocketFactory getDefaultSSLSocketFactory() { 629 if (defaultSslSocketFactory == null) { 630 try { 631 SSLContext sslContext = SSLContext.getInstance("TLS"); 632 sslContext.init(null, null, null); 633 defaultSslSocketFactory = sslContext.getSocketFactory(); 634 } catch (GeneralSecurityException e) { 635 throw new AssertionError(); // The system has no TLS. Just give up. 636 } 637 } 638 return defaultSslSocketFactory; 639 } 640 641 /** Returns a shallow copy of this OkHttpClient. */ clone()642 @Override public OkHttpClient clone() { 643 return new OkHttpClient(this); 644 } 645 } 646