## File: README.md

OkHttp
======

See the [project website][okhttp] for documentation and APIs.

HTTP is the way modern applications network. It’s how we exchange data & media. Doing HTTP
efficiently makes your stuff load faster and saves bandwidth.

OkHttp is an HTTP client that’s efficient by default:

 * HTTP/2 support allows all requests to the same host to share a socket.
 * Connection pooling reduces request latency (if HTTP/2 isn’t available).
 * Transparent GZIP shrinks download sizes.
 * Response caching avoids the network completely for repeat requests.

OkHttp perseveres when the network is troublesome: it will silently recover from common connection
problems. If your service has multiple IP addresses, OkHttp will attempt alternate addresses if the
first connect fails. This is necessary for IPv4+IPv6 and services hosted in redundant data
centers. OkHttp supports modern TLS features (TLS 1.3, ALPN, certificate pinning). It can be
configured to fall back for broad connectivity.

Using OkHttp is easy. Its request/response API is designed with fluent builders and immutability. It
supports both synchronous blocking calls and async calls with callbacks.

A well behaved user agent
-------------------------

OkHttp follows modern HTTP specifications such as

* HTTP Semantics - [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110)
* HTTP Caching- [RFC 9111](https://datatracker.ietf.org/doc/html/rfc9111)
* HTTP/1.1 - [RFC 9112](https://datatracker.ietf.org/doc/html/rfc9112)
* HTTP/2 - [RFC 9113](https://datatracker.ietf.org/doc/html/rfc9113)
* Websockets - [RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455)
* SSE - [Server-sent events](https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events)

Where the spec is ambiguous, OkHttp follows modern user agents such as popular Browsers or common HTTP Libraries.

OkHttp is principled and avoids being overly configurable, especially when such configuration is
to workaround a buggy server, test invalid scenarios or that contradict the relevant RFC.
Other HTTP libraries exist that fill that gap allowing extensive customisation including potentially
invalid requests.

Example Limitations

* Does not allow GET with a body.
* Cache is not an interface with alternative implementations.

Get a URL
---------

This program downloads a URL and prints its contents as a string. [Full source][get_example].

```java
OkHttpClient client = new OkHttpClient();

String run(String url) throws IOException {
  Request request = new Request.Builder()
      .url(url)
      .build();

  try (Response response = client.newCall(request).execute()) {
    return response.body().string();
  }
}
```


Post to a Server
----------------

This program posts data to a service. [Full source][post_example].

```java
public static final MediaType JSON = MediaType.get("application/json");

OkHttpClient client = new OkHttpClient();

String post(String url, String json) throws IOException {
  RequestBody body = RequestBody.create(json, JSON);
  Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();
  try (Response response = client.newCall(request).execute()) {
    return response.body().string();
  }
}
```

Further examples are on the [OkHttp Recipes page][recipes].


Requirements
------------

OkHttp works on Android 5.0+ (API level 21+) and Java 8+.

On Android, OkHttp uses [AndroidX Startup][androidx_startup]. If you disable the initializer in the manifest,
then apps are responsible for calling `OkHttp.initialize(applicationContext)` in `Application.onCreate`.

OkHttp depends on [Okio][okio] for high-performance I/O and the [Kotlin standard library][kotlin]. Both are small libraries with strong backward-compatibility.

We highly recommend you keep OkHttp up-to-date. As with auto-updating web browsers, staying current
with HTTPS clients is an important defense against potential security problems. [We
track][tls_history] the dynamic TLS ecosystem and adjust OkHttp to improve connectivity and
security.

OkHttp uses your platform's built-in TLS implementation. On Java platforms OkHttp also supports
[Conscrypt][conscrypt], which integrates [BoringSSL](https://github.com/google/boringssl) with Java. OkHttp will use Conscrypt if it is
the first security provider:

```java
Security.insertProviderAt(Conscrypt.newProvider(), 1);
```

The OkHttp `3.12.x` branch supports Android 2.3+ (API level 9+) and Java 7+. These platforms lack
support for TLS 1.2 and should not be used.


Releases
--------

Our [change log][changelog] has release history.

The latest release is available on [Maven Central](https://search.maven.org/artifact/com.squareup.okhttp3/okhttp/5.5.0/jar).

```kotlin
implementation("com.squareup.okhttp3:okhttp:5.5.0")
```

Snapshot builds are [available][snap]. [R8 and ProGuard][r8_proguard] rules are available.

Also, we have a [bill of materials (BOM)][bom] available to help you keep OkHttp artifacts up to date and be sure about version compatibility.

```kotlin
    dependencies {
       // define a BOM and its version
       implementation(platform("com.squareup.okhttp3:okhttp-bom:5.5.0"))

       // define any required OkHttp artifacts without version
       implementation("com.squareup.okhttp3:okhttp")
       implementation("com.squareup.okhttp3:logging-interceptor")
    }
```

Maven and JVM Projects
----------------------

OkHttp is published as a Kotlin Multiplatform project. While Gradle handles this automatically,
Maven projects must select between `okhttp-jvm` and `okhttp-android`. The `okhttp` artifact will be empty in
Maven projects.

```xml
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>okhttp-bom</artifactId>
      <version>5.2.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
```



```xml
<dependency>
  <groupId>com.squareup.okhttp3</groupId>
  <artifactId>okhttp-jvm</artifactId>
  
  <version>5.1.0</version>
</dependency>

<dependency>
  <groupId>com.squareup.okhttp3</groupId>
  <artifactId>mockwebserver3</artifactId>
</dependency>

<dependency>
  <groupId>com.squareup.okhttp3</groupId>
  <artifactId>logging-interceptor</artifactId>
</dependency>
```

MockWebServer
-------------

OkHttp includes a library for testing HTTP, HTTPS, and HTTP/2 clients.

The latest release is available on [Maven Central](https://search.maven.org/artifact/com.squareup.okhttp3/mockwebserver/5.5.0/jar).

```kotlin
testImplementation("com.squareup.okhttp3:mockwebserver3:5.5.0")
```

MockWebServer is used for firstly for internal testing, and for basic testing of apps using OkHttp client.
It is not a full featured HTTP testing library that is developed standalone. It is not being actively developed
for new features. As such you might find your needs outgrow MockWebServer and you may which to use a
more full featured testing library such as [MockServer](https://www.mock-server.com/).

GraalVM Native Image
--------------------

Building your native images with [GraalVM] should work automatically.

See the okcurl module for an example build.

```shell
$ ./gradlew okcurl:nativeImage
$ ./okcurl/build/graal/okcurl https://httpbin.org/get
```

Java Modules
------------

OkHttp (5.2+) implements Java 9 Modules.

With this in place Java builds should fail if apps attempt to use internal packages.

```
error: package okhttp3.internal.platform is not visible
    okhttp3.internal.platform.Platform.get();
                    ^
  (package okhttp3.internal.platform is declared in module okhttp3,
    which does not export it to module com.bigco.sdk)
```

The stable public API is based on the list of defined modules:

- okhttp3
- okhttp3.brotli
- okhttp3.coroutines
- okhttp3.dnsoverhttps
- okhttp3.java.net.cookiejar
- okhttp3.logging
- okhttp3.sse
- okhttp3.tls
- okhttp3.urlconnection
- mockwebserver3
- mockwebserver3.junit4
- mockwebserver3.junit5

License
-------

```
Copyright 2019 Square, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```

 [GraalVM]: https://www.graalvm.org/
 [androidx_startup]: https://developer.android.com/jetpack/androidx/releases/startup
 [bom]: https://docs.gradle.org/6.2/userguide/platforms.html#sub:bom_import
 [changelog]: https://lysine.dev/okhttp/changelog/
 [conscrypt]: https://github.com/google/conscrypt/
 [get_example]: https://raw.github.com/lysine-dev/okhttp/master/samples/guide/src/main/java/okhttp3/guide/GetExample.java
 [kotlin]: https://kotlinlang.org/
 [okhttp3_pro]: https://raw.githubusercontent.com/lysine-dev/okhttp/master/okhttp/okhttp3.pro
 [okhttp]: https://lysine.dev/okhttp/
 [okhttp_312x]: https://github.com/lysine-dev/okhttp/tree/okhttp_3.12.x
 [okio]: https://github.com/lysine-dev/okio
 [post_example]: https://raw.github.com/lysine-dev/okhttp/master/samples/guide/src/main/java/okhttp3/guide/PostExample.java
 [r8_proguard]: https://lysine.dev/okhttp/features/r8_proguard/
 [recipes]: https://lysine.dev/okhttp/recipes/
 [snap]: https://s01.oss.sonatype.org/content/repositories/snapshots/
 [tls_history]: https://lysine.dev/okhttp/tls_configuration_history/

---

## File: android-test/src/androidTest/README.md

Android Test
============

A gradle module for running Android instrumentation tests on a device or emulator.

1. Add an Emulator named `pixel5`, if you don't already have one

```
$ sdkmanager --install "system-images;android-29;google_apis;x86"
$ echo "no" | avdmanager --verbose create avd --force --name "pixel5" --device "pixel" --package "system-images;android-29;google_apis;x86" --tag "google_apis" --abi "x86"
```

2. Run an Emulator using Android Studio or from command line.

```
$ emulator -no-window -no-snapshot-load @pixel5
```

2. Turn on logs with logcat

```
$ adb logcat '*:E' OkHttp:D Http2:D TestRunner:D TaskRunner:D OkHttpTest:D GnssHAL_GnssInterface:F DeviceStateChecker:F memtrack:F
...
01-01 12:53:32.811 10999 11089 D OkHttp  : [49 ms] responseHeadersEnd: Response{protocol=h2, code=200, message=, url=https://1.1.1.1/dns-query?dns=AAABAAABAAAAAAAAA3d3dwhmYWNlYm9vawNjb20AABwAAQ}
01-01 12:53:32.811 10999 11089 D OkHttp  : [49 ms] responseBodyStart
01-01 12:53:32.811 10999 11089 D OkHttp  : [49 ms] responseBodyEnd: byteCount=128
01-01 12:53:32.811 10999 11089 D OkHttp  : [49 ms] connectionReleased
01-01 12:53:32.811 10999 11089 D OkHttp  : [49 ms] callEnd
01-01 12:53:32.816 10999 11090 D OkHttp  : [54 ms] responseHeadersStart
01-01 12:53:32.816 10999 11090 D OkHttp  : [54 ms] responseHeadersEnd: Response{protocol=h2, code=200, message=, url=https://1.1.1.1/dns-query?dns=AAABAAABAAAAAAAAA3d3dwhmYWNlYm9vawNjb20AAAEAAQ}
01-01 12:53:32.817 10999 11090 D OkHttp  : [55 ms] responseBodyStart
01-01 12:53:32.818 10999 11090 D OkHttp  : [56 ms] responseBodyEnd: byteCount=128
01-01 12:53:32.818 10999 11090 D OkHttp  : [56 ms] connectionReleased
01-01 12:53:32.818 10999 11090 D OkHttp  : [56 ms] callEnd
```

3. Run tests using gradle

```
$ ANDROID_SDK_ROOT=/Users/myusername/Library/Android/sdk ./gradlew :android-test:connectedCheck -PandroidBuild=true
...
> Task :android-test:connectedDebugAndroidTest
...
11:55:40 V/InstrumentationResultParser: Time: 13.271
11:55:40 V/InstrumentationResultParser:
11:55:40 V/InstrumentationResultParser: OK (12 tests)
...
11:55:40 I/XmlResultReporter: XML test result file generated at /Users/myusername/workspace/okhttp/android-test/build/outputs/androidTest-results/connected/TEST-pixel3a-Q(AVD) - 10-android-test-.xml. Total tests 13, passed 11, assumption_failure 1, ignored 1,
...
BUILD SUCCESSFUL in 1m 30s
63 actionable tasks: 61 executed, 2 up-to-date

```

n.b. use ANDROID_SERIAL=emulator-5554 or similar if you need to select between devices.

---

## File: docs/features/caching.md

Caching
=======

OkHttp implements an optional, off by default, Cache. OkHttp aims for RFC correct and
pragmatic caching behaviour, following common real-world browser like Firefox/Chrome and
server behaviour when ambiguous.

# Basic Usage

```kotlin
  private val client: OkHttpClient = OkHttpClient.Builder()
      .cache(Cache(
          directory = File(application.cacheDir, "http_cache"),
          // $0.05 worth of phone storage in 2020
          maxSize = 50L * 1024L * 1024L // 50 MiB
      ))
      .build()
```

## EventListener events

Cache Events are exposed via the EventListener API.  Typical scenarios are below.

### Cache Hit

In the ideal scenario the cache can fulfill the request without any conditional call to the network.
This will skip the normal events such as DNS, connecting to the network, and downloading the response body.

As recommended by the HTTP RFC the max age of a document is defaulted to 10% of the
document's age at the time it was served based on "Last-Modified". Default expiration dates aren't used for URIs
containing a query.

 - CallStart
 - **CacheHit**
 - CallEnd

### Cache Miss

Under a cache miss the normal request events are seen but an additional event shows the presence of the cache.
Cache Miss will be typical if the item has not been read from the network, is uncacheable, or is past it's
lifetime based on Response cache headers.

 - CallStart
 - **CacheMiss**
 - ProxySelectStart
 - ... Standard Events ...
 - CallEnd

### Conditional Cache Hit

When cache flags require checking the cache results are still valid an early cacheConditionalHit event is
received followed by a cache hit or miss.  Critically in the cache hit scenario the server won’t send the response body.

The response will have non-null `cacheResponse` and `networkResponse`. The cacheResponse will be used as the top level
response only if the response code is HTTP/1.1 304 Not Modified.

 - CallStart
 - **CacheConditionalHit**
 - ConnectionAcquired
 - ... Standard Events...
 - ResponseBodyEnd _(0 bytes)_
 - **CacheHit**
 - ConnectionReleased
 - CallEnd

## Cache directory

The cache directory must be exclusively owned by a single instance.

Deleting the cache when it is no longer needed can be done.  However this may delete the purpose of the cache
which is designed to persist between app restarts.

```kotlin
cache.delete()
```

## Pruning the Cache

Pruning the entire Cache to clear space temporarily can be done using evictAll.

```kotlin
cache.evictAll()
```

Removing individual items can be done using the urls iterator.
This would be typical after a user initiates a force refresh by a pull to refresh type action.

```java
    val urlIterator = cache.urls()
    while (urlIterator.hasNext()) {
      if (urlIterator.next().startsWith("https://www.google.com/")) {
        urlIterator.remove()
      }
    }
```

### Troubleshooting

1. Valid cacheable responses are not being cached

Make sure you are reading responses fully as unless they are read fully, cancelled or stalled Responses will not be cached.

### Overriding normal cache behaviour

See [`Cache`](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-cache/) documentation.

---

## File: docs/features/calls.md

# Calls

The HTTP client’s job is to accept your request and produce its response. This is simple in theory but it gets tricky in practice.

## [Requests](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-request/)

Each HTTP request contains a URL, a method (like `GET` or `POST`), and a list of headers. Requests may also contain a body: a data stream of a specific content type.

## [Responses](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-response/)

The response answers the request with a code (like 200 for success or 404 for not found), headers, and its own optional body.

## Rewriting Requests

When you provide OkHttp with an HTTP request, you’re describing the request at a high-level: _“fetch me this URL with these headers.”_ For correctness and efficiency, OkHttp rewrites your request before transmitting it.

OkHttp may add headers that are absent from the original request, including `Content-Length`, `Transfer-Encoding`, `User-Agent`, `Host`, `Connection`, and `Content-Type`. It will add an `Accept-Encoding` header for transparent response compression unless the header is already present. If you’ve got cookies, OkHttp will add a `Cookie` header with them.

Some requests will have a cached response. When this cached response isn’t fresh, OkHttp can do a _conditional GET_ to download an updated response if it’s newer than what’s cached. This requires headers like `If-Modified-Since` and `If-None-Match` to be added.

## Rewriting Responses

If transparent compression was used, OkHttp will drop the corresponding response headers `Content-Encoding` and `Content-Length` because they don’t apply to the decompressed response body.

If a conditional GET was successful, responses from the network and cache are merged as directed by the spec.

## Follow-up Requests

When your requested URL has moved, the webserver will return a response code like `302` to indicate the document’s new URL. OkHttp will follow the redirect to retrieve a final response.

If the response issues an authorization challenge, OkHttp will ask the [`Authenticator`](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-authenticator/) (if one is configured) to satisfy the challenge. If the authenticator supplies a credential, the request is retried with that credential included.

## Retrying Requests

Sometimes connections fail: either a pooled connection was stale and disconnected, or the webserver itself couldn’t be reached. OkHttp will retry the request with a different route if one is available.

## [Calls](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-call/)

With rewrites, redirects, follow-ups and retries, your simple request may yield many requests and responses. OkHttp uses `Call` to model the task of satisfying your request through however many intermediate requests and responses are necessary. Typically this isn’t many! But it’s comforting to know that your code will continue to work if your URLs are redirected or if you failover to an alternate IP address.

Calls are executed in one of two ways:

 * **Synchronous:** your thread blocks until the response is readable.
 * **Asynchronous:** you enqueue the request on any thread, and get [called back](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-callback/) on another thread when the response is readable.

Calls can be canceled from any thread. This will fail the call if it hasn’t yet completed! Code that is writing the request body or reading the response body will suffer an `IOException` when its call is canceled.

## Dispatch

For synchronous calls, you bring your own thread and are responsible for managing how many simultaneous requests you make. Too many simultaneous connections wastes resources; too few harms latency.

For asynchronous calls, [`Dispatcher`](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-dispatcher/) implements policy for maximum simultaneous requests. You can set maximums per-webserver (default is 5), and overall (default is 64).

---

## File: docs/features/connections.md

Connections
===========

Although you provide only the URL, OkHttp plans its connection to your webserver using three types: URL, Address, and Route.

### [URLs](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-http-url/)

URLs (like `https://github.com/lysine-dev/okhttp`) are fundamental to HTTP and the Internet. In addition to being a universal, decentralized naming scheme for everything on the web, they also specify how to access web resources.

URLs are abstract:

 * They specify that the call may be plaintext (`http`) or encrypted (`https`), but not which cryptographic algorithms should be used. Nor do they specify how to verify the peer's certificates (the [HostnameVerifier](https://developer.android.com/reference/javax/net/ssl/HostnameVerifier.html)) or which certificates can be trusted (the [SSLSocketFactory](https://developer.android.com/reference/org/apache/http/conn/ssl/SSLSocketFactory.html)).
 * They don't specify whether a specific proxy server should be used or how to authenticate with that proxy server.

They're also concrete: each URL identifies a specific path (like `/lysine-dev/okhttp`) and query (like `?q=sharks&lang=en`). Each webserver hosts many URLs.

### [Addresses](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-address/)

Addresses specify a webserver (like `github.com`) and all of the **static** configuration necessary to connect to that server: the port number, HTTPS settings, and preferred network protocols (like HTTP/2).

URLs that share the same address may also share the same underlying TCP socket connection. Sharing a connection has substantial performance benefits: lower latency, higher throughput (due to [TCP slow start](https://www.igvita.com/2011/10/20/faster-web-vs-tcp-slow-start/)) and conserved battery. OkHttp uses a [ConnectionPool](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-connection-pool/) that automatically reuses HTTP/1.x connections and multiplexes HTTP/2 connections.

In OkHttp some fields of the address come from the URL (scheme, hostname, port) and the rest come from the [OkHttpClient](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-ok-http-client/).

### [Routes](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-route/)

Routes supply the **dynamic** information necessary to actually connect to a webserver. This is the specific IP address to attempt (as discovered by a DNS query), the exact proxy server to use (if a [ProxySelector](https://developer.android.com/reference/java/net/ProxySelector.html) is in use), and which version of TLS to negotiate (for HTTPS connections).

There may be many routes for a single address. For example, a webserver that is hosted in multiple datacenters may yield multiple IP addresses in its DNS response.

In limited situations OkHttp will retry a route if connecting fails:

 * When making an HTTPS connection through an HTTP proxy, the proxy may issue an authentication challenge. OkHttp will call the proxy [authenticator](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-authenticator/) and try again.
 * When making TLS connections with multiple [connection specs](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-connection-spec/), these are attempted in sequence until the TLS handshake succeeds.

### [Connections](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-connection/)

When you request a URL with OkHttp, here's what it does:

 1. It uses the URL and configured OkHttpClient to create an **address**. This address specifies how we'll connect to the webserver.
 2. It attempts to retrieve a connection with that address from the **connection pool**.
 3. If it doesn't find a connection in the pool, it selects a **route** to attempt. This usually means making a DNS request to get the server's IP addresses. It then selects a TLS version and proxy server if necessary.
 4. If it's a new route, it connects by building either a direct socket connection, a TLS tunnel (for HTTPS over an HTTP proxy), or a direct TLS connection. It does TLS handshakes as necessary. This step may be retried for tunnel challenges and TLS handshake failures.
 5. It sends the HTTP request and reads the response.

If there's a problem with the connection, OkHttp will select another route and try again. This allows OkHttp to recover when a subset of a server's addresses are unreachable. It's also useful when a pooled connection is stale or if the attempted TLS version is unsupported.

Once the response has been received, the connection will be returned to the pool so it can be reused for a future request. Connections are evicted from the pool after a period of inactivity.

### [Fast Fallback](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-ok-http-client/-builder/fast-fallback)

Since version 5.0, `OkHttpClient` supports fast fallback, which is our implementation of Happy Eyeballs [RFC 6555](https://datatracker.ietf.org/doc/html/rfc6555).

With fast fallback, OkHttp attempts to connect to multiple web servers concurrently. It keeps whichever route connects first and cancels all of the others. Its rules are:

 * Prefer to alternate IP addresses from different address families, (IPv6 / IPv4), starting with IPv6.
 * Don't start a new attempt until 250 ms after the most recent attempt was started.
 * Keep whichever TCP connection succeeds first and cancel all the others.
 * Race TCP only. Only attempt a TLS handshake on the winning TCP connection.

If the winner of the TCP handshake race fails to succeed in a TLS handshake, the process is restarted with the remaining routes.

---

## File: docs/features/events.md

Events
======

Events allow you to capture metrics on your application’s HTTP calls. Use events to monitor:

 * The size and frequency of the HTTP calls your application makes. If you’re making too many calls, or your calls are too large, you should know about it!
 * The performance of these calls on the underlying network. If the network’s performance isn’t sufficient, you need to either improve the network or use less of it.

### EventListener

Subclass [EventListener](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-event-listener/) and override methods for the events you are interested in. In a successful HTTP call with no redirects or retries the sequence of events is described by this flow.



Here’s a [sample event listener](https://github.com/lysine-dev/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/PrintEventsNonConcurrent.java) that prints each event with a timestamp.

```java
class PrintingEventListener extends EventListener {
  private long callStartNanos;

  private void printEvent(String name) {
    long nowNanos = System.nanoTime();
    if (name.equals("callStart")) {
      callStartNanos = nowNanos;
    }
    long elapsedNanos = nowNanos - callStartNanos;
    System.out.printf("%.3f %s%n", elapsedNanos / 1000000000d, name);
  }

  @Override public void callStart(Call call) {
    printEvent("callStart");
  }

  @Override public void callEnd(Call call) {
    printEvent("callEnd");
  }

  @Override public void dnsStart(Call call, String domainName) {
    printEvent("dnsStart");
  }

  @Override public void dnsEnd(Call call, String domainName, List inetAddressList) {
    printEvent("dnsEnd");
  }

  ...
}
```

We make a couple calls:

```java
Request request = new Request.Builder()
    .url("https://publicobject.com/helloworld.txt")
    .build();

System.out.println("REQUEST 1 (new connection)");
try (Response response = client.newCall(request).execute()) {
  // Consume and discard the response body.
  response.body().source().readByteString();
}

System.out.println("REQUEST 2 (pooled connection)");
try (Response response = client.newCall(request).execute()) {
  // Consume and discard the response body.
  response.body().source().readByteString();
}
```

And the listener prints the corresponding events:

```
REQUEST 1 (new connection)
0.000 callStart
0.010 dnsStart
0.017 dnsEnd
0.025 connectStart
0.117 secureConnectStart
0.586 secureConnectEnd
0.586 connectEnd
0.587 connectionAcquired
0.588 requestHeadersStart
0.590 requestHeadersEnd
0.591 responseHeadersStart
0.675 responseHeadersEnd
0.676 responseBodyStart
0.679 responseBodyEnd
0.679 connectionReleased
0.680 callEnd
REQUEST 2 (pooled connection)
0.000 callStart
0.001 connectionAcquired
0.001 requestHeadersStart
0.001 requestHeadersEnd
0.002 responseHeadersStart
0.082 responseHeadersEnd
0.082 responseBodyStart
0.082 responseBodyEnd
0.083 connectionReleased
0.083 callEnd
```

Notice how no connect events are fired for the second call. It reused the connection from the first request for dramatically better performance.

### EventListener.Factory

In the preceding example we used a field, `callStartNanos`, to track the elapsed time of each event. This is handy, but it won’t work if multiple calls are executing concurrently. To accommodate this, use a `Factory` to create a new `EventListener` instance for each `Call`. This allows each listener to keep call-specific state.

This [sample factory](https://github.com/lysine-dev/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/PrintEvents.java) creates a unique ID for each call and uses that ID to differentiate calls in log messages.

```java
class PrintingEventListener extends EventListener {
  public static final Factory FACTORY = new Factory() {
    final AtomicLong nextCallId = new AtomicLong(1L);

    @Override public EventListener create(Call call) {
      long callId = nextCallId.getAndIncrement();
      System.out.printf("%04d %s%n", callId, call.request().url());
      return new PrintingEventListener(callId, System.nanoTime());
    }
  };

  final long callId;
  final long callStartNanos;

  public PrintingEventListener(long callId, long callStartNanos) {
    this.callId = callId;
    this.callStartNanos = callStartNanos;
  }

  private void printEvent(String name) {
    long elapsedNanos = System.nanoTime() - callStartNanos;
    System.out.printf("%04d %.3f %s%n", callId, elapsedNanos / 1000000000d, name);
  }

  @Override public void callStart(Call call) {
    printEvent("callStart");
  }

  @Override public void callEnd(Call call) {
    printEvent("callEnd");
  }

  ...
}
```

We can use this listener to race a pair of concurrent HTTP requests:

```java
Request washingtonPostRequest = new Request.Builder()
    .url("https://www.washingtonpost.com/")
    .build();
client.newCall(washingtonPostRequest).enqueue(new Callback() {
  ...
});

Request newYorkTimesRequest = new Request.Builder()
    .url("https://www.nytimes.com/")
    .build();
client.newCall(newYorkTimesRequest).enqueue(new Callback() {
  ...
});
```

Running this race over home WiFi shows the Times (`0002`) completes just slightly sooner than the Post (`0001`):

```
0001 https://www.washingtonpost.com/
0001 0.000 callStart
0002 https://www.nytimes.com/
0002 0.000 callStart
0002 0.010 dnsStart
0001 0.013 dnsStart
0001 0.022 dnsEnd
0002 0.019 dnsEnd
0001 0.028 connectStart
0002 0.025 connectStart
0002 0.072 secureConnectStart
0001 0.075 secureConnectStart
0001 0.386 secureConnectEnd
0002 0.390 secureConnectEnd
0002 0.400 connectEnd
0001 0.403 connectEnd
0002 0.401 connectionAcquired
0001 0.404 connectionAcquired
0001 0.406 requestHeadersStart
0002 0.403 requestHeadersStart
0001 0.414 requestHeadersEnd
0002 0.411 requestHeadersEnd
0002 0.412 responseHeadersStart
0001 0.415 responseHeadersStart
0002 0.474 responseHeadersEnd
0002 0.475 responseBodyStart
0001 0.554 responseHeadersEnd
0001 0.555 responseBodyStart
0002 0.554 responseBodyEnd
0002 0.554 connectionReleased
0002 0.554 callEnd
0001 0.624 responseBodyEnd
0001 0.624 connectionReleased
0001 0.624 callEnd
```

The `EventListener.Factory` also makes it possible to limit metrics to a subset of calls. This one captures metrics on a random 10%:

```java
class MetricsEventListener extends EventListener {
  private static final Factory FACTORY = new Factory() {
    @Override public EventListener create(Call call) {
      if (Math.random() < 0.10) {
        return new MetricsEventListener(call);
      } else {
        return EventListener.NONE;
      }
    }
  };

  ...
}
```

### Events with Failures

When an operation fails, a failure method is called. This is `connectFailed()` for failures while building a connection to the server, and `callFailed()` when the HTTP call fails permanently. When a failure happens it is possible that a `start` event won’t have a corresponding `end` event.



### Events with Retries and Follow-Ups

OkHttp is resilient and can automatically recover from some connectivity failures. In this case, the `connectFailed()` event is not terminal and not followed by `callFailed()`. Event listeners will receive multiple events of the same type when retries are attempted.

A single HTTP call may require follow-up requests to be made to handle authentication challenges, redirects, and HTTP-layer timeouts. In such cases multiple connections, requests, and responses may be attempted. Follow-ups are another reason a single call may trigger multiple events of the same type.



### Availability

Events is available as a public API in OkHttp 3.11. Future releases may introduce new event types; you will need to override the corresponding methods to handle them.

---

## File: docs/features/https.md

HTTPS
=====

OkHttp attempts to balance two competing concerns:

 * **Connectivity** to as many hosts as possible. That includes advanced hosts that run the latest versions of [boringssl](https://boringssl.googlesource.com/boringssl/) and less out of date hosts running older versions of [OpenSSL](https://www.openssl.org/).
 * **Security** of the connection. This includes verification of the remote webserver with certificates and the privacy of data exchanged with strong ciphers.

When negotiating a connection to an HTTPS server, OkHttp needs to know which [TLS versions](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-tls-version/) and [cipher suites](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-cipher-suite/) to offer. A client that wants to maximize connectivity would include obsolete TLS versions and weak-by-design cipher suites. A strict client that wants to maximize security would be limited to only the latest TLS version and strongest cipher suites.

Specific security vs. connectivity decisions are implemented by [ConnectionSpec](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-connection-spec/). OkHttp includes four built-in connection specs:

 * `RESTRICTED_TLS` is a secure configuration, intended to meet stricter compliance requirements.
 * `MODERN_TLS` is a secure configuration that connects to modern HTTPS servers.
 * `COMPATIBLE_TLS` is a secure configuration that connects to secure–but not current–HTTPS servers.
 * `CLEARTEXT` is an insecure configuration that is used for `http://` URLs.

These loosely follow the model set in [Google Cloud Policies](https://cloud.google.com/load-balancing/docs/ssl-policies-concepts). We [track changes](../security/tls_configuration_history.md) to this policy.

By default, OkHttp will attempt a `MODERN_TLS` connection.  However by configuring the client connectionSpecs you can allow a fall back to `COMPATIBLE_TLS` connection if the modern configuration fails.

```java
OkHttpClient client = new OkHttpClient.Builder()
    .connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS))
    .build();
```

The TLS versions and cipher suites in each spec can change with each release. For example, in OkHttp 2.2 we dropped support for SSL 3.0 in response to the [POODLE](https://googleonlinesecurity.blogspot.ca/2014/10/this-poodle-bites-exploiting-ssl-30.html) attack. And in OkHttp 2.3 we dropped support for [RC4](https://en.wikipedia.org/wiki/RC4#Security). As with your desktop web browser, staying up-to-date with OkHttp is the best way to stay secure.

You can build your own connection spec with a custom set of TLS versions and cipher suites. For example, this configuration is limited to three highly-regarded cipher suites. Its drawback is that it requires Android 5.0+ and a similarly current webserver.

```java
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
    .tlsVersions(TlsVersion.TLS_1_2)
    .cipherSuites(
          CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
          CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
          CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
    .build();

OkHttpClient client = new OkHttpClient.Builder()
    .connectionSpecs(Collections.singletonList(spec))
    .build();
```

### Debugging TLS Handshake Failures

The TLS handshake requires clients and servers to share a common TLS version and cipher suite. This
depends on the JVM or Android version, OkHttp version, and web server configuration. If there is no
common cipher suite and TLS version, your call will fail like this:

```
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7f2719a89e80:
    Failure in SSL library, usually a protocol error
        error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake
        failure (external/openssl/ssl/s23_clnt.c:770 0x7f2728a53ea0:0x00000000)
    at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
```

You can check a web server's configuration using [Qualys SSL Labs][qualys]. OkHttp's TLS
configuration history is [tracked here](../security/tls_configuration_history.md).

Applications expected to be installed on older Android devices should consider adopting the
[Google Play Services’ ProviderInstaller][provider_installer]. This will increase security for users
and increase connectivity with web servers.

### Certificate Pinning ([.kt][CertificatePinningKotlin], [.java][CertificatePinningJava])

By default, OkHttp trusts the certificate authorities of the host platform. This strategy maximizes connectivity, but it is subject to certificate authority attacks such as the [2011 DigiNotar attack](https://www.computerworld.com/article/2510951/cybercrime-hacking/hackers-spied-on-300-000-iranians-using-fake-google-certificate.html). It also assumes your HTTPS servers’ certificates are signed by a certificate authority.

Use [CertificatePinner](https://lysine.dev/okhttp/5.x/okhttp/okhttp3/-certificate-pinner/) to restrict which certificates and certificate authorities are trusted. Certificate pinning increases security, but limits your server team’s abilities to update their TLS certificates. **Do not use certificate pinning without the blessing of your server’s TLS administrator!**

=== ":material-language-kotlin: Kotlin"
    ```kotlin
      private val client = OkHttpClient.Builder()
          .certificatePinner(
              CertificatePinner.Builder()
                  .add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
                  .build())
          .build()

      fun run() {
        val request = Request.Builder()
            .url("https://publicobject.com/robots.txt")
            .build()

        client.newCall(request).execute().use { response ->
          if (!response.isSuccessful) throw IOException("Unexpected code $response")

          for (certificate in response.handshake!!.peerCertificates) {
            println(CertificatePinner.pin(certificate))
          }
        }
      }
    ```
=== ":material-language-java: Java"
    ```java
      private final OkHttpClient client = new OkHttpClient.Builder()
          .certificatePinner(
              new CertificatePinner.Builder()
                  .add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
                  .build())
          .build();

      public void run() throws Exception {
        Request request = new Request.Builder()
            .url("https://publicobject.com/robots.txt")
            .build();

        try (Response response = client.newCall(request).execute()) {
          if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

          for (Certificate certificate : response.handshake().peerCertificates()) {
            System.out.println(CertificatePinner.pin(certificate));
          }
        }
      }
    ```

### Customizing Trusted Certificates ([.kt][CustomTrustKotlin], [.java][CustomTrustJava])

The full code sample shows how to replace the host platform’s certificate authorities with your own set. As above, **do not use custom certificates without the blessing of your server’s TLS administrator!**

=== ":material-language-kotlin: Kotlin"
    ```kotlin
      private val client: OkHttpClient

      init {
        val trustManager = trustManagerForCertificates(trustedCertificatesInputStream())
        val sslContext = SSLContext.getInstance("TLS")
        sslContext.init(null, arrayOf(trustManager), null)
        val sslSocketFactory = sslContext.socketFactory

        client = OkHttpClient.Builder()
            .sslSocketFactory(sslSocketFactory, trustManager)
            .build()
      }

      fun run() {
        val request = Request.Builder()
            .url("https://publicobject.com/helloworld.txt")
            .build()

        client.newCall(request).execute().use { response ->
          if (!response.isSuccessful) throw IOException("Unexpected code $response")

          for ((name, value) in response.headers) {
            println("$name: $value")
          }

          println(response.body!!.string())
        }
      }

      /**
       * Returns an input stream containing one or more certificate PEM files. This implementation just
       * embeds the PEM files in Java strings; most applications will instead read this from a resource
       * file that gets bundled with the application.
       */
      private fun trustedCertificatesInputStream(): InputStream {
        ... // Full source omitted. See sample.
      }

      private fun trustManagerForCertificates(inputStream: InputStream): X509TrustManager {
        ... // Full source omitted. See sample.
      }
    ```
=== ":material-language-java: Java"
    ```java
      private final OkHttpClient client;

      public CustomTrust() {
        X509TrustManager trustManager;
        SSLSocketFactory sslSocketFactory;
        try {
          trustManager = trustManagerForCertificates(trustedCertificatesInputStream());
          SSLContext sslContext = SSLContext.getInstance("TLS");
          sslContext.init(null, new TrustManager[] { trustManager }, null);
          sslSocketFactory = sslContext.getSocketFactory();
        } catch (GeneralSecurityException e) {
          throw new RuntimeException(e);
        }

        client = new OkHttpClient.Builder()
            .sslSocketFactory(sslSocketFactory, trustManager)
            .build();
      }

      public void run() throws Exception {
        Request request = new Request.Builder()
            .url("https://publicobject.com/helloworld.txt")
            .build();

        Response response = client.newCall(request).execute();
        System.out.println(response.body().string());
      }

      private InputStream trustedCertificatesInputStream() {
        ... // Full source omitted. See sample.
      }

      public SSLContext sslContextForTrustedCertificates(InputStream in) {
        ... // Full source omitted. See sample.
      }
    ```

 [CustomTrustJava]: https://github.com/lysine-dev/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java
 [CustomTrustKotlin]: https://github.com/lysine-dev/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/kt/CustomTrust.kt
 [CertificatePinningJava]: https://github.com/lysine-dev/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CertificatePinning.java
 [CertificatePinningKotlin]: https://github.com/lysine-dev/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/kt/CertificatePinning.kt
 [provider_installer]: https://developer.android.com/training/articles/security-gms-provider
 [qualys]: https://www.ssllabs.com/ssltest/

---

## File: docs/features/interceptors.md

Interceptors
============

Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls. Here's a simple interceptor that logs the outgoing request and the incoming response.

```java
class LoggingInterceptor implements Interceptor {
  @Override public Response intercept(Interceptor.Chain chain) throws IOException {
    Request request = chain.request();

    long t1 = System.nanoTime();
    logger.info(String.format("Sending request %s on %s%n%s",
        request.url(), chain.connection(), request.headers()));

    Response response = chain.proceed(request);

    long t2 = System.nanoTime();
    logger.info(String.format("Received response for %s in %.1fms%n%s",
        response.request().url(), (t2 - t1) / 1e6d, response.headers()));

    return response;
  }
}
```

A call to `chain.proceed(request)` is a critical part of each interceptor’s implementation. This simple-looking method is where all the HTTP work happens, producing a response to satisfy the request. If `chain.proceed(request)` is being called more than once previous response bodies must be closed.

Interceptors can be chained. Suppose you have both a compressing interceptor and a checksumming interceptor: you'll need to decide whether data is compressed and then checksummed, or checksummed and then compressed. OkHttp uses lists to track interceptors, and interceptors are called in order.



### Application Interceptors

Interceptors are registered as either _application_ or _network_ interceptors. We'll use the `LoggingInterceptor` defined above to show the difference.

Register an _application_ interceptor by calling `addInterceptor()` on `OkHttpClient.Builder`:

```java
OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new LoggingInterceptor())
    .build();

Request request = new Request.Builder()
    .url("http://www.publicobject.com/helloworld.txt")
    .header("User-Agent", "OkHttp Example")
    .build();

Response response = client.newCall(request).execute();
response.body().close();
```

The URL `http://www.publicobject.com/helloworld.txt` redirects to `https://publicobject.com/helloworld.txt`, and OkHttp follows this redirect automatically. Our application interceptor is called **once** and the response returned from `chain.proceed()` has the redirected response:

```
INFO: Sending request http://www.publicobject.com/helloworld.txt on null
User-Agent: OkHttp Example

INFO: Received response for https://publicobject.com/helloworld.txt in 1179.7ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/plain
Content-Length: 1759
Connection: keep-alive
```

We can see that we were redirected because `response.request().url()` is different from `request.url()`. The two log statements log two different URLs.

### Network Interceptors

Registering a network interceptor is quite similar. Call `addNetworkInterceptor()` instead of `addInterceptor()`:

```java
OkHttpClient client = new OkHttpClient.Builder()
    .addNetworkInterceptor(new LoggingInterceptor())
    .build();

Request request = new Request.Builder()
    .url("http://www.publicobject.com/helloworld.txt")
    .header("User-Agent", "OkHttp Example")
    .build();

Response response = client.newCall(request).execute();
response.body().close();
```

When we run this code, the interceptor runs twice. Once for the initial request to `http://www.publicobject.com/helloworld.txt`, and another for the redirect to `https://publicobject.com/helloworld.txt`.

```
INFO: Sending request http://www.publicobject.com/helloworld.txt on Connection{www.publicobject.com:80, proxy=DIRECT hostAddress=54.187.32.157 cipherSuite=none protocol=http/1.1}
User-Agent: OkHttp Example
Host: www.publicobject.com
Connection: Keep-Alive
Accept-Encoding: gzip

INFO: Received response for http://www.publicobject.com/helloworld.txt in 115.6ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/html
Content-Length: 193
Connection: keep-alive
Location: https://publicobject.com/helloworld.txt

INFO: Sending request https://publicobject.com/helloworld.txt on Connection{publicobject.com:443, proxy=DIRECT hostAddress=54.187.32.157 cipherSuite=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA protocol=http/1.1}
User-Agent: OkHttp Example
Host: publicobject.com
Connection: Keep-Alive
Accept-Encoding: gzip

INFO: Received response for https://publicobject.com/helloworld.txt in 80.9ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/plain
Content-Length: 1759
Connection: keep-alive
```

The network requests also contain more data, such as the `Accept-Encoding: gzip` header added by OkHttp to advertise support for response compression. The network interceptor's `Chain` has a non-null `Connection` that can be used to interrogate the IP address and TLS configuration that were used to connect to the webserver.

### Choosing between application and network interceptors

Each interceptor chain has relative merits.

**Application interceptors**

 * Don't need to worry about intermediate responses like redirects and retries.
 * Are always invoked once, even if the HTTP response is served from the cache.
 * Observe the application's original intent. Unconcerned with OkHttp-injected headers like `If-None-Match`.
 * Permitted to short-circuit and not call `Chain.proceed()`.
 * Permitted to retry and make multiple calls to `Chain.proceed()`.
 * Can adjust Call timeouts using withConnectTimeout, withReadTimeout, withWriteTimeout.

**Network Interceptors**

 * Able to operate on intermediate responses like redirects and retries.
 * Not invoked for cached responses that short-circuit the network.
 * Observe the data just as it will be transmitted over the network.
 * Access to the `Connection` that carries the request.

### Rewriting Requests

Interceptors can add, remove, or replace request headers. They can also transform the body of those requests that have one. For example, you can use an application interceptor to add request body compression if you're connecting to a webserver known to support it.

```java
/** This interceptor compresses the HTTP request body. Many webservers can't handle this! */
final class GzipRequestInterceptor implements Interceptor {
  @Override public Response intercept(Interceptor.Chain chain) throws IOException {
    Request originalRequest = chain.request();
    if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
      return chain.proceed(originalRequest);
    }

    Request compressedRequest = originalRequest.newBuilder()
        .header("Content-Encoding", "gzip")
        .method(originalRequest.method(), gzip(originalRequest.body()))
        .build();
    return chain.proceed(compressedRequest);
  }

  private RequestBody gzip(final RequestBody body) {
    return new RequestBody() {
      @Override public MediaType contentType() {
        return body.contentType();
      }

      @Override public long contentLength() {
        return -1; // We don't know the compressed length in advance!
      }

      @Override public void writeTo(BufferedSink sink) throws IOException {
        BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
        body.writeTo(gzipSink);
        gzipSink.close();
      }
    };
  }
}
```

### Rewriting Responses

Symmetrically, interceptors can rewrite response headers and transform the response body. This is generally more dangerous than rewriting request headers because it may violate the webserver's expectations!

If you're in a tricky situation and prepared to deal with the consequences, rewriting response headers is a powerful way to work around problems. For example, you can fix a server's misconfigured `Cache-Control` response header to enable better response caching:

```java
/** Dangerous interceptor that rewrites the server's cache-control header. */
private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
  @Override public Response intercept(Interceptor.Chain chain) throws IOException {
    Response originalResponse = chain.proceed(chain.request());
    return originalResponse.newBuilder()
        .header("Cache-Control", "max-age=60")
        .build();
  }
};
```

Typically this approach works best when it complements a corresponding fix on the webserver!

---

## File: docs/features/r8_proguard.md

R8 / ProGuard
=============

If you use OkHttp as a dependency in an Android project which uses R8 as a default compiler you
don't have to do anything. The specific rules are [already bundled][okhttp3_pro] into the JAR which can be
interpreted by R8 automatically.

If you, however, don't use R8 you have to apply the rules from [this file][okhttp3_pro]. You might
also need rules from [Okio][okio] which is a dependency of this library.

 [okhttp3_pro]: https://raw.githubusercontent.com/lysine-dev/okhttp/master/okhttp/okhttp3.pro
 [okio]: https://lysine.dev/okio/