# OkHttp Admin & Architecture Guide

This guide is the deep reference for engineers, architects, and library maintainers integrating, operating, or extending **OkHttp** — the HTTP client for Java, Kotlin, and Android maintained by Square/Block. It documents OkHttp's architecture, its complete public configuration surface, the full module ecosystem, security posture, and internal design, all derived directly from the OkHttp 5.x source (commit `7a35098`).

Where the [User Guide](square__okhttp__UserGuide.md) shows *how to make requests*, this guide explains *how OkHttp is built and how to operate it well in production*.

---

## 1. Executive Summary

OkHttp is a mature, widely-deployed HTTP client distributed as a set of small, focused JVM/Android libraries under the Maven group `com.squareup.okhttp3`. It is the de-facto networking layer for a large share of the Android ecosystem and the transport beneath higher-level clients such as Retrofit.

**Key characteristics:**

- **Immutable, builder-based API.** `OkHttpClient`, `Request`, `Response`, `Headers`, `HttpUrl`, and `CacheControl` are immutable value types created through `Builder` classes. Clients are cheaply derived with `newBuilder()`.
- **Connection efficiency by default.** A shared `ConnectionPool` reuses HTTP/1.x sockets and multiplexes HTTP/2. Transparent gzip, response caching, and Happy Eyeballs fast-fallback are built in.
- **Resilience.** Automatic recovery from unreachable IPs, stale pooled connections, and unreachable proxies; automatic redirect, authentication-challenge, and retry handling.
- **Layered request processing.** Every call flows through an ordered chain of interceptors (application then OkHttp's own then network), making behaviour observable and extensible.
- **Pluggable trust & DNS.** TLS configuration, certificate pinning, custom trust managers, and DNS (including DNS-over-HTTPS) are all replaceable.
- **Standards-driven.** Implements RFC 9110/9111/9112/9113 (HTTP semantics, caching, HTTP/1.1, HTTP/2), RFC 6455 (WebSockets), and SSE. Deliberately minimal in configurability where configuration would only serve to violate specs.

**Runtime footprint:** Android 5.0+ (API 21+) and Java 8+. Depends only on [Okio](https://square.github.io/okio/) and the Kotlin standard library. License: **Apache 2.0**.

---

## 2. Architecture

### 2.1 The request lifecycle

OkHttp models the work of satisfying one logical HTTP request — possibly involving redirects, authentication follow-ups, and retries across routes — as a single `Call`. A high-level request (`Request`) is rewritten, dispatched, connected, transmitted, and the response is read back, rewritten, and returned.

```text
        ┌──────────────────────────────────────────────────────────────┐
        │                       OkHttpClient                            │
        │  (shared config: dispatcher, connection pool, interceptors,   │
        │   cache, dns, TLS, timeouts, protocols)                       │
        └───────────────┬───────────────────────────────────────────────┘
                        │ newCall(request)
                        ▼
                 ┌────────────┐   execute() / enqueue(Callback)
                 │    Call    │──────────────────────────────────┐
                 └────────────┘                                  │
                        │                                        ▼
                        │                                  ┌────────────┐
                        │            async path            │ Dispatcher │
                        │  ◀───────────────────────────────│ (limits +  │
                        │                                  │  executor) │
                        ▼                                  └────────────┘
        ┌──────────────────────────────────────────┐
        │            Interceptor Chain               │
        │  1. Application interceptors (your code)   │
        │  2. RetryAndFollowUpInterceptor            │
        │  3. BridgeInterceptor (cookies, gzip,      │
        │     Content-Length, User-Agent, Host…)     │
        │  4. CacheInterceptor (Cache read/write)    │
        │  5. ConnectInterceptor (pool → route →     │
        │     socket/TLS)                            │
        │  6. Network interceptors (your code)       │
        │  7. CallServerInterceptor (write request,  │
        │     read response)                         │
        └──────────────────┬─────────────────────────┘
                           ▼
        ┌──────────────────────────────────────────┐
        │  Connection  ←  Route  ←  Address  ← URL   │
        │  (ConnectionPool reuses & multiplexes)     │
        └──────────────────────────────────────────┘
                           ▼
                     Origin server
```

> [!NOTE]
> The interceptor chain is the heart of OkHttp's design. Built-in behaviours (retries, header bridging, caching, connecting, transmitting) are themselves interceptors. Your application and network interceptors are inserted at the ends of this chain.

### 2.2 URL → Address → Route → Connection

OkHttp resolves *what to connect to* through four layered types ([source: `docs/features/connections.md`](https://square.github.io/okhttp/5.x/)):

| Type | Nature | What it captures |
|------|--------|------------------|
| **`HttpUrl`** | Abstract | scheme (`http`/`https`), host, port, path, query, fragment. Says *what* to fetch, not *how*. |
| **`Address`** | Static | The server plus all static connection config: port, HTTPS settings (TLS factory, hostname verifier, pinner), proxy authenticator, DNS, protocols, connection specs. URLs sharing an address can share a socket. |
| **`Route`** | Dynamic | A concrete IP (from DNS), a specific proxy (from `ProxySelector`), and the TLS version to negotiate. One address may yield many routes. |
| **`Connection`** | Live | An established socket (direct, TLS, or tunneled through an HTTP proxy) carrying requests. Pooled and reused. |

When you request a URL, OkHttp: (1) builds an `Address` from the URL + client config; (2) tries to reuse a pooled `Connection` for that address; (3) if none, selects a `Route` (DNS lookup, proxy, TLS version); (4) connects (direct socket / TLS tunnel / direct TLS, with handshakes); (5) sends the request and reads the response; then returns the connection to the pool for reuse, evicting it after inactivity.

### 2.3 Request rewriting

OkHttp rewrites your high-level request before transmission for correctness and efficiency. It may add `Content-Length`, `Transfer-Encoding`, `User-Agent`, `Host`, `Connection`, `Content-Type`, `Accept-Encoding: gzip` (unless present), and a `Cookie` header (if a `CookieJar` has cookies). For stale cached responses it performs conditional GETs by adding `If-Modified-Since` / `If-None-Match`. On the response side, if transparent compression was used it drops `Content-Encoding` and `Content-Length` (they no longer describe the decompressed body), and merges network + cache responses for successful conditional GETs.

### 2.4 Dispatch model

- **Synchronous** (`Call.execute()`): the caller's thread blocks; the caller manages concurrency.
- **Asynchronous** (`Call.enqueue(Callback)`): the `Dispatcher` runs the call on its `ExecutorService` and invokes the callback on a dispatcher thread. The dispatcher enforces `maxRequests` (default **64**) and `maxRequestsPerHost` (default **5**).

### 2.5 Module topology

OkHttp is a multi-module Gradle/Kotlin-Multiplatform project. The core `okhttp` module targets `commonJvmAndroid` with `jvmMain` and `androidMain` source sets; feature modules layer onto it.

```text
okhttp (core: okhttp3)
 ├── mockwebserver3              test server (+ junit4 / junit5 / deprecated mockwebserver)
 ├── logging-interceptor         okhttp3.logging
 ├── okhttp-tls                  okhttp3.tls (HeldCertificate, HandshakeCertificates)
 ├── okhttp-sse                  okhttp3.sse (EventSource)
 ├── okhttp-dnsoverhttps         okhttp3.dnsoverhttps (DnsOverHttps)
 ├── okhttp-brotli               okhttp3.brotli (BrotliInterceptor)
 ├── okhttp-zstd                 okhttp3.zstd (Zstd)
 ├── okhttp-coroutines           okhttp3.coroutines (executeAsync)
 ├── okhttp-urlconnection        JavaNetAuthenticator, JavaNetCookieJar
 ├── okhttp-java-net-cookiejar   okhttp3.java.net.cookiejar.JavaNetCookieJar
 ├── okhttp-idna-mapping-table   IDNA host-name mapping
 ├── okhttp-bom                  Bill of Materials (version alignment)
 └── okcurl                      CLI (okhttp3.curl)
```

> [!NOTE]
> Each publishable module ships a checked-in `api/*.api` signature file (the Kotlin binary-compatibility validator output). These files are the authoritative, exhaustive list of every public class, field, and function — useful when auditing the API surface or planning an upgrade.

### 2.6 Repository structure

| Path | Contents |
|------|----------|
| `okhttp/` | Core client. Public API in `src/commonJvmAndroid/kotlin/okhttp3/`; internals in `okhttp3/internal/`. Android specifics in `src/androidMain/`. |
| `mockwebserver/`, `mockwebserver-junit4/`, `-junit5/`, `-deprecated/` | Test server and integrations. |
| `okhttp-*` modules | Optional features (see topology above). |
| `okcurl/` | Clikt-based CLI entry point. |
| `samples/` | Runnable examples: `guide/recipes` (30+ recipes), `crawler`, `slack`, `static-server`, `unixdomainsockets`, `tlssurvey`, `compare`. |
| `docs/` | MkDocs site: `features/*.md` (conceptual docs), `changelogs/`, `security/`, `contribute/`. |
| `android-test/`, `regression-test/`, `container-tests/`, `okhttp-osgi-tests/`, `maven-tests/`, `native-image-tests/` | Cross-environment test suites. |
| `build-logic/` | Gradle convention plugins (`okhttp.jvm-conventions`, etc.). |

---

## 3. System Requirements

| Concern | Requirement |
|---------|-------------|
| Java | 8 or newer |
| Android | 5.0+ (API level 21+) |
| Runtime dependencies | Okio, Kotlin standard library (both small, backward-compatible) |
| Build (for contributors) | Gradle with the configuration cache and isolated-projects enabled; multi-module KMP build |
| Optional TLS provider | [Conscrypt](https://github.com/google/conscrypt) (BoringSSL-backed) — used automatically if installed as the first JCE security provider |
| License | Apache License 2.0 |

> [!IMPORTANT]
> The legacy `3.12.x` branch supports Android 2.3+ (API 9+) and Java 7+, but those platforms lack TLS 1.2 and must not be used for production. There is no security backport guarantee for that branch.

Optional Conscrypt activation:

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

---

## 4. Configuration Reference — `OkHttpClient.Builder`

`OkHttpClient` is configured exclusively through `OkHttpClient.Builder`. The table below lists every public builder setting with its default value, taken from the source.

### 4.1 Timeouts

| Method | Default | Meaning |
|--------|---------|---------|
| `callTimeout(Long, TimeUnit)` / `(Duration)` | `0` (no timeout) | Whole-call budget: DNS + connect + write + server + read, across all redirects/retries. For WebSockets/duplex, only the initial setup. |
| `connectTimeout(Long, TimeUnit)` / `(Duration)` | `10_000` ms | TCP connect to host. |
| `readTimeout(Long, TimeUnit)` / `(Duration)` | `10_000` ms | Socket reads and each response-body read. |
| `writeTimeout(Long, TimeUnit)` / `(Duration)` | `10_000` ms | Each request-body write. |
| `pingInterval(Long, TimeUnit)` / `(Duration)` | `0` (disabled) | HTTP/2 & WebSocket ping cadence; a missed pong fails the connection. |
| `webSocketCloseTimeout(Long, TimeUnit)` / `(Duration)` | `60_000` ms | Wait for graceful WebSocket shutdown after `close()`. |

All timeout values must be `0` (off) or between 1 and `Integer.MAX_VALUE` when converted to milliseconds. Each method has `long+TimeUnit`, `java.time.Duration`, and Kotlin `Duration` overloads.

### 4.2 Connections & protocols

| Method | Default | Meaning |
|--------|---------|---------|
| `connectionPool(ConnectionPool)` | new pool | Socket reuse pool. A default is created and shared if unset. |
| `dispatcher(Dispatcher)` | new `Dispatcher()` | Async concurrency policy + executor. |
| `protocols(List<Protocol>)` | `[HTTP_2, HTTP_1_1]` | Preferred protocols; ALPN-negotiated over HTTPS. Must contain `HTTP_1_1` or be `[H2_PRIOR_KNOWLEDGE]`; never `HTTP_1_0` or null. `SPDY_3` is silently removed. |
| `connectionSpecs(List<ConnectionSpec>)` | `[MODERN_TLS, CLEARTEXT]` | TLS/cleartext negotiation policies, tried in order. |
| `fastFallback(Boolean)` | `true` | Happy Eyeballs (RFC 6555) concurrent connect racing. `false` reverts to 4.x sequential connects. |
| `retryOnConnectionFailure(Boolean)` | `true` | Silently recover from unreachable IPs, stale pooled connections, and unreachable proxies. Set `false` when retries would be destructive. |
| `followRedirects(Boolean)` | `true` | Follow HTTP redirects. |
| `followSslRedirects(Boolean)` | `true` | Follow cross-scheme redirects (HTTP↔HTTPS); still gated by `followRedirects`. |
| `dns(Dns)` | `Dns.SYSTEM` | Hostname → IP resolver. |
| `socketFactory(SocketFactory)` | system default | Creates unconnected sockets (must not be an `SSLSocketFactory`). |
| `proxy(Proxy)` | none | Explicit proxy; takes precedence over `proxySelector`. Use `Proxy.NO_PROXY` to disable proxying entirely. |
| `proxySelector(ProxySelector)` | system default | Proxy selection when no explicit proxy is set. |

### 4.3 TLS & trust

| Method | Default | Meaning |
|--------|---------|---------|
| `sslSocketFactory(SSLSocketFactory, X509TrustManager)` | platform default | Secure HTTPS connections. **Preferred** overload. |
| `sslSocketFactory(SSLSocketFactory)` | — | **Deprecated** (DeprecationLevel.ERROR): forces reflection to recover the trust manager. |
| `hostnameVerifier(HostnameVerifier)` | `OkHostnameVerifier` | Confirms a server certificate matches the requested hostname. |
| `certificatePinner(CertificatePinner)` | `CertificatePinner.DEFAULT` (no pins) | Restricts trusted certificates per host. |

> [!CAUTION]
> If no connection spec is TLS-capable (CLEARTEXT-only client), the client has no SSL socket factory and accessing `sslSocketFactory` throws `IllegalStateException("CLEARTEXT-only client")`. The builder validates this invariant at `build()` time.

### 4.4 Behaviour & integrations

| Method | Default | Meaning |
|--------|---------|---------|
| `addInterceptor(Interceptor)` | — | Append an application interceptor (sees the original request, runs once). |
| `addNetworkInterceptor(Interceptor)` | — | Append a network interceptor (sees redirects/retries and the live `Connection`). |
| `authenticator(Authenticator)` | `Authenticator.NONE` | Responds to origin (`401`) challenges. |
| `proxyAuthenticator(Authenticator)` | `Authenticator.NONE` | Responds to proxy (`407`) challenges. |
| `cookieJar(CookieJar)` | `CookieJar.NO_COOKIES` | Stores/sends cookies. |
| `cache(Cache)` | none | Response cache (see §6). |
| `eventListener(EventListener)` | `EventListener.NONE` | Single shared metrics listener. |
| `eventListenerFactory(EventListener.Factory)` | — | Per-call metrics listener factory. |
| `minWebSocketMessageToCompress(Long)` | `1024` | Minimum outbound WS message size (bytes) eligible for compression; `0` compresses all. |

> [!TIP]
> Mutating a route-affecting setting (`dns`, `proxy`, `proxySelector`, `proxyAuthenticator`, `socketFactory`, `sslSocketFactory`, `connectionSpecs`, `protocols`, `hostnameVerifier`, `certificatePinner`) on a derived builder resets the internal `RouteDatabase` so stale route blacklists don't leak between configurations.

---

## 5. Public API Reference

The core `okhttp3` package (artifact `okhttp`, signatures from `okhttp/api/jvm/okhttp.api`) exposes the following public types. Builder/value types are immutable; interfaces are extension points.

### 5.1 Core request/response types

| Type | Kind | Purpose |
|------|------|---------|
| `OkHttpClient` | class (`Call.Factory`, `WebSocket.Factory`) | The configured client. `newCall()`, `newWebSocket()`, `newBuilder()`, plus read-only accessors for every setting. |
| `Request` | immutable | One HTTP request: `url()`, `method()`, `headers()`, `body()`, `cacheControl()`, `tag()`, `toCurl()`, `newBuilder()`. |
| `Request.Builder` | builder | `url(...)`, `get/head/post/put/patch/delete/method(...)`, `header/addHeader/removeHeader`, `headers`, `cacheControl`, `tag`, `gzip()`, `cacheUrlOverride`. |
| `Response` | immutable (`Closeable`) | `code()`, `message()`, `isSuccessful()`, `isRedirect()`, `headers()`, `body()`, `peekBody(n)`, `request()`, `protocol()`, `handshake()`, `cacheResponse()`, `networkResponse()`, `priorResponse()`, `challenges()`, `trailers()`, `sentRequestAtMillis()`, `receivedResponseAtMillis()`. |
| `Response.Builder` | builder | Construct synthetic responses (used by interceptors and tests). |
| `RequestBody` | abstract | `contentType()`, `contentLength()`, `writeTo(sink)`, `isOneShot()`, `isDuplex()`, `sha256()`, plus many `create(...)` factories (String, byte[], File, FileDescriptor, ByteString, Okio Path). |
| `ResponseBody` | abstract (`Closeable`) | `contentType()`, `contentLength()`, `string()`, `bytes()`, `byteString()`, `source()`, `byteStream()`, `charStream()`. |
| `Call` | interface (`Cloneable`) | `execute()`, `enqueue(callback)`, `cancel()`, `isExecuted()`, `isCanceled()`, `request()`, `timeout()`, `clone()`, `addEventListener()`, `tag(...)`. |
| `Call.Factory` | interface | `newCall(request)`. |
| `Callback` | interface | `onResponse(call, response)`, `onFailure(call, e)`. |

### 5.2 Headers, URLs, media types, bodies

| Type | Purpose |
|------|---------|
| `Headers` / `Headers.Builder` | Multi-map of header name/value pairs; `get`, `values`, `name(i)`, `value(i)`, `getDate`, `getInstant`, `toMultimap`, `of(...)`. Builder adds `add`, `addUnsafeNonAscii`, `set`, `removeAll`. |
| `HttpUrl` / `HttpUrl.Builder` | Typed URL with full encode/decode accessors, `resolve()`, `redact()`, `topPrivateDomain()`, `queryParameter*`, `defaultPort()`, conversions to/from `java.net.URI`/`URL`. |
| `MediaType` | Parsed `Content-Type`: `type()`, `subtype()`, `charset()`, `parameter()`; `MediaType.get(str)` / `parse(str)`. |
| `FormBody` / `FormBody.Builder` | `application/x-www-form-urlencoded` body. |
| `MultipartBody` / `.Builder` / `.Part` | `multipart/*` body with predefined types `MIXED`, `ALTERNATIVE`, `DIGEST`, `PARALLEL`, `FORM`. |
| `MultipartReader` / `.Part` | Parse multipart **responses**. |
| `CacheControl` / `.Builder` | `Cache-Control` directive model; constants `FORCE_CACHE`, `FORCE_NETWORK`. |

### 5.3 Connection, TLS & negotiation types

| Type | Purpose |
|------|---------|
| `Connection` | Live connection: `route()`, `socket()`, `handshake()`, `protocol()`. |
| `ConnectionPool` | Socket reuse pool: `connectionCount()`, `idleConnectionCount()`, `evictAll()`. |
| `ConnectionSpec` / `.Builder` | TLS policy; constants `RESTRICTED_TLS`, `MODERN_TLS`, `COMPATIBLE_TLS`, `CLEARTEXT`. |
| `CipherSuite` | ~150 named TLS cipher-suite constants; `forJavaName()`, `javaName()`. |
| `TlsVersion` | enum `SSL_3_0`, `TLS_1_0`, `TLS_1_1`, `TLS_1_2`, `TLS_1_3`. |
| `Protocol` | enum `HTTP_1_0`, `HTTP_1_1`, `HTTP_2`, `H2_PRIOR_KNOWLEDGE`, `HTTP_3`, `QUIC`, `SPDY_3` (deprecated). |
| `Handshake` | TLS handshake details: `tlsVersion()`, `cipherSuite()`, `peerCertificates()`, `localCertificates()`, principals. |
| `CertificatePinner` / `.Builder` / `.Pin` | Certificate pinning; static `pin()`, `sha256Hash()`, `sha1Hash()`. |
| `Address` | Static connection configuration for a server. |
| `Route` | A concrete IP + proxy + spec attempt; `requiresTunnel()`. |
| `Dns` | interface; `lookup(host)`; constant `Dns.SYSTEM`. |
| `Dispatcher` | Async concurrency: `maxRequests`, `maxRequestsPerHost`, `queuedCalls`, `runningCalls`, `cancelAll`, `executorService`. |

### 5.4 Extension-point interfaces & callbacks

| Type | Purpose |
|------|---------|
| `Interceptor` / `Interceptor.Chain` | Observe/rewrite/retry calls. The chain exposes `request()`, `proceed()`, `connection()`, `call()`, the resolved timeouts, and `with*` methods to derive a chain with overridden config/timeouts. `Interceptor.invoke { }` (Kotlin) builds one from a lambda. |
| `Authenticator` | Respond to challenges; constants `NONE`, `JAVA_NET_AUTHENTICATOR`. |
| `CookieJar` | Cookie storage; constant `NO_COOKIES`. |
| `EventListener` / `.Factory` | ~30 lifecycle callbacks (DNS, connect, secure-connect, request/response headers & body, cache hit/miss, retry/follow-up decisions, etc.); `NONE`; `plus()` to combine. |
| `WebSocket` / `WebSocket.Factory` / `WebSocketListener` | WebSocket send/close/cancel and `onOpen/onMessage/onClosing/onClosed/onFailure`. |
| `Credentials` | `basic(user, pass[, charset])` helper. |
| `Challenge` | A parsed `WWW-Authenticate`/`Proxy-Authenticate` challenge: `scheme()`, `realm()`, `authParams()`, `charset()`. |
| `Cookie` / `.Builder` | RFC 6265 cookie model; `parse()`, `parseAll()`, `matches()`. |
| `CompressionInterceptor` / `.DecompressionAlgorithm` | Pluggable response decompression; `Gzip` is built in. |
| `TrailersSource` | Source of HTTP trailers; constant `EMPTY`. |
| `OkHttp` | `OkHttp.VERSION` constant; `OkHttp.initialize(context)` on Android. |

### 5.5 Feature-module APIs

| Module | Public API |
|--------|-----------|
| `logging-interceptor` | `HttpLoggingInterceptor` (`Level` = NONE/BASIC/HEADERS/BODY; `redactHeader`, `redactQueryParams`; pluggable `Logger`), `LoggingEventListener` (+ `.Factory`). |
| `okhttp-tls` | `HeldCertificate` (+ `.Builder`: `commonName`, `addSubjectAlternativeName`, `validityInterval`, `serialNumber`, `certificateAuthority`, `signedBy`, `rsa2048`/`ecdsa256`), `HandshakeCertificates` (+ `.Builder`: `addTrustedCertificate`, `addPlatformTrustedCertificates`, `addInsecureHost`, `heldCertificate`), `Certificates` (PEM encode/decode). |
| `okhttp-sse` | `EventSource`, `EventSource.Factory`, `EventSourceListener` (`onOpen/onEvent/onClosed/onFailure`), `EventSources.createFactory(...)` / `processResponse(...)`. |
| `okhttp-dnsoverhttps` | `DnsOverHttps` (+ `.Builder`: `client`, `url`, `includeIPv6`, `post`, `resolvePrivate/PublicAddresses`, `bootstrapDnsHosts`, `systemDns`). |
| `okhttp-brotli` | `BrotliInterceptor.INSTANCE`, `Brotli` algorithm. |
| `okhttp-zstd` | `Zstd` decompression algorithm. |
| `okhttp-coroutines` | `Call.executeAsync()` suspend extension. |
| `okhttp-urlconnection` | `JavaNetAuthenticator`, `JavaNetCookieJar`. |
| `okhttp-java-net-cookiejar` | `okhttp3.java.net.cookiejar.JavaNetCookieJar(CookieHandler)`. |
| `mockwebserver3` | `MockWebServer`, `MockResponse` (+ `.Builder`), `RecordedRequest`, `Dispatcher`, `QueueDispatcher`, `SocketEffect`, `PushPromise`. |

---

## 6. Caching Internals

The optional `Cache` is a disk-backed, RFC-9111-aligned response store with browser-like heuristics. It is implemented as the `CacheInterceptor` within the chain.

**Construction:** `Cache(File directory, long maxSize)` or `Cache(FileSystem, Path, long maxSize)` (Okio file system). One directory per `Cache`; the directory is exclusively owned.

**Behaviour:**

- Default freshness for documents without explicit expiry is **10% of the document's age** at serve time (based on `Last-Modified`); not applied to URLs containing a query.
- Three outcomes, observable via `EventListener`: **Cache Hit** (no network), **Cache Miss** (network used; uncacheable/expired/never-fetched), **Conditional Hit** (`cacheConditionalHit` then a revalidation request; the cached body is reused only on `304 Not Modified`, so both `cacheResponse()` and `networkResponse()` are non-null).
- A response is stored only if its body is fully read, canceled, or stalled.

**Operations & stats:** `evictAll()`, `delete()`, `urls()` iterator (with `remove()`), `flush()`, `close()`, `size()`, `maxSize()`, and counters `hitCount()`, `networkCount()`, `requestCount()`, `writeSuccessCount()`, `writeAbortCount()`.

> [!WARNING]
> Sharing a cache directory between two `Cache` instances or processes corrupts it. In multi-process apps, give each process its own directory or a single shared client.

---

## 7. Security Analysis

OkHttp's threat model centers on protecting transport confidentiality/integrity while maximizing connectivity. Security-relevant subsystems and operational guidance follow.

### 7.1 TLS posture

- Defaults to `MODERN_TLS` + `CLEARTEXT`; uses the platform TLS stack (or Conscrypt if installed first). TLS versions/cipher suites in each `ConnectionSpec` evolve per release — historically OkHttp dropped SSL 3.0 (POODLE) and RC4 as attacks emerged.
- `RESTRICTED_TLS` is available for stricter compliance environments.
- Hostname verification (`OkHostnameVerifier`) always runs in addition to certificate trust, even with custom Android trust managers.

> [!IMPORTANT]
> Staying current with OkHttp is itself a security control: the library tracks the TLS ecosystem and removes weak primitives. Pin your dependency to a recent 5.x release and update regularly.

### 7.2 Certificate pinning

`CertificatePinner` lets you constrain trust to specific public-key hashes, mitigating CA compromise (e.g. the 2011 DigiNotar attack). Pinning is double-edged: an uncoordinated server certificate rotation will hard-fail every pinned client.

> [!CAUTION]
> Never deploy certificate pins without your server TLS team's sign-off and a rotation plan. Prefer pinning an intermediate/CA key over a leaf certificate to reduce rotation breakage, and ship backup pins.

### 7.3 Authentication & credential handling

- `Authenticator` callbacks must guard against retry loops by returning `null` when an `Authorization` header is already present (see community issue [#9477](https://github.com/square/okhttp/issues/9477), "Infinite Authentication Loop in Proxy CONNECT Tunnel").
- `Credentials.basic` Base64-encodes credentials — Basic auth offers no confidentiality without TLS.
- `HttpUrl.redact()` produces a credential-stripped URL safe for logs.

### 7.4 Logging hygiene

`HttpLoggingInterceptor` at `HEADERS`/`BODY` level will log sensitive headers and payloads. Use `redactHeader("Authorization")`, `redactHeader("Cookie")`, and `redactQueryParams(...)`, and never enable `BODY` logging for authenticated traffic in production.

### 7.5 Known security-relevant issues (community-reported)

These open/closed issues from the project tracker inform hardening decisions; consult the upstream issue and your installed version before relying on a given behaviour:

| Issue | Topic | Operational note |
|-------|-------|------------------|
| [#9476](https://github.com/square/okhttp/issues/9476) | SSRF via unrestricted redirect following | If you fetch untrusted/user-supplied URLs, consider `followRedirects(false)` and validate redirect targets in an interceptor. |
| [#9477](https://github.com/square/okhttp/issues/9477) | Infinite auth loop in proxy CONNECT tunnel | Guard `Authenticator` against re-attempting with an existing `Authorization`. |
| [#9434](https://github.com/square/okhttp/issues/9434) | `InsecureAndroidTrustManager` MITM concern | Never use insecure/all-trusting trust managers outside tests. |
| [#9472](https://github.com/square/okhttp/issues/9472) (closed) | Predictable WebSocket masking keys | Fixed; keep current. |
| [#9473](https://github.com/square/okhttp/issues/9473) (closed) | Gzip decompression bomb | Bound response sizes for untrusted servers; don't blindly `string()` arbitrary bodies. |
| [#9474](https://github.com/square/okhttp/issues/9474) (closed) | CRLF header injection via `addUnsafeNonAscii()` | Avoid `addUnsafeNonAscii` with untrusted header values. |
| [#9451](https://github.com/square/okhttp/issues/9451) | `HttpUrl.isDotDot` path-traversal forms | Relevant if you use OkHttp URL parsing for sandboxing path checks. |
| [#9335](https://github.com/square/okhttp/issues/9335) | Cache entries not stored correctly on Windows | On Windows, validate cache hit rates; excessive requests may indicate this bug. |

> [!CAUTION]
> When fetching attacker-controllable URLs (webhooks, link unfurling, image proxies), treat redirect following and decompression as attack surface: disable or constrain redirects, cap body sizes, and resolve/deny internal IP ranges via a custom `Dns` or network interceptor to prevent SSRF.

---

## 8. Operations

### 8.1 Lifecycle management

OkHttp requires **no explicit shutdown** — idle dispatcher threads and pooled connections self-release; HTTP/2 daemon threads exit when idle. For aggressive resource reclamation (CLI tools, short-lived workers):

```java
client.dispatcher().executorService().shutdown(); // rejects future calls
client.connectionPool().evictAll();
if (client.cache() != null) client.cache().close();
```

> [!WARNING]
> After `executorService().shutdown()` the client rejects new calls. After `cache().close()`, issuing a call against that cache crashes — close the cache only during teardown.

### 8.2 Tuning for throughput

- Raise `Dispatcher.maxRequests` / `maxRequestsPerHost` for high-concurrency async workloads, and back the dispatcher with an executor sized to match.
- Keep one shared `OkHttpClient` (and thus one `ConnectionPool`) per process so connections are actually reused.
- Prefer HTTP/2 (the default) for many concurrent requests to one host — they multiplex over a single socket.
- Use `pingInterval` on long-lived connections to detect dead peers promptly.

> [!NOTE]
> Issue [#9443](https://github.com/square/okhttp/issues/9443) notes that the dispatcher executor must actually be *able* to run `maxRequests` concurrently — a too-small thread pool silently caps real concurrency below the configured maximum.

### 8.3 Observability

- **Metrics:** an `EventListener.Factory` gives per-call timing for every network phase; sample (e.g. 10%) to bound overhead. Cache hit/miss/conditional events flow through the same listener.
- **Logging:** `LoggingEventListener.Factory` for phase timings, or `HttpLoggingInterceptor` for wire-level request/response logs (redact secrets).
- **Pool inspection:** `connectionPool().connectionCount()` / `idleConnectionCount()` and `dispatcher().runningCallsCount()` / `queuedCallsCount()` expose live load.

### 8.4 Proxy & DNS operations

- Route all traffic through a fixed proxy with `proxy(...)`, or delegate to `proxySelector(...)`. `proxyAuthenticator(...)` handles proxy `407` challenges.
- Replace name resolution wholesale with a custom `Dns`, or use `DnsOverHttps` for encrypted resolution (configure a bootstrap client and DoH endpoint).

---

## 9. Code Quality, Patterns & Conventions

- **Kotlin-first, Java-friendly.** Core is Kotlin with `@JvmName`/`@JvmStatic`/`@JvmOverloads` and `Companion`-object factories so Java callers get idiomatic APIs (`Headers.of(...)`, `MediaType.get(...)`).
- **Immutability + builders.** Value types are immutable; the only mutation path is a `Builder`. `newBuilder()` enables cheap, copy-on-write derivation that shares pools.
- **Deprecation discipline.** Property-style getters that replaced old method-style accessors are retained as `@Deprecated(level = ERROR)` `-deprecated_*` shims (visible throughout the `.api` files) to preserve binary compatibility while steering callers to `val` accessors.
- **Binary-compatibility validation.** Checked-in `api/*.api` signature files are enforced in CI, preventing accidental public-API breakage.
- **Internal encapsulation.** Everything under `okhttp3.internal` is non-public by convention (the open issue [#9435](https://github.com/square/okhttp/issues/9435) tracks formalizing this as `internal` or promoting parts to API). Do not depend on internal classes.
- **KMP source sets.** `commonJvmAndroid` holds shared JVM/Android code; `androidMain` and `jvmMain` carry platform specifics, allowing one codebase to target both.
- **Multiplatform value semantics.** Inline-class-backed durations appear in the `.api` as mangled names (e.g. `callTimeout-LRDsOJo`) — these are Kotlin `Duration` overloads, not separate Java API.

---

## 10. Testing Strategy

OkHttp dogfoods its own `MockWebServer` and maintains an unusually broad test matrix:

| Suite | Validates |
|-------|-----------|
| `mockwebserver3` + unit tests | Protocol behaviour against a real scriptable server (delays, throttling, chunking, HTTP/2 push, TLS handshake failures, 100-Continue, WebSockets). |
| `android-test`, `android-test-app`, `regression-test` | On-device/emulator instrumentation (e.g. ALPN, SNI, Let's Encrypt trust). |
| `container-tests` | Behaviour inside containers. |
| `okhttp-osgi-tests` | OSGi bundle compatibility. |
| `maven-tests` | Consuming OkHttp via Maven + the BOM version range. |
| `native-image-tests` | GraalVM native-image compatibility (reachability metadata under `META-INF/native-image`). |
| `okhttp-hpacktests` | HTTP/2 HPACK header-compression conformance (shared test cases). |
| `samples/tlssurvey`, `samples/compare` | TLS ecosystem surveys and cross-client comparison. |
| `fuzzing` | Fuzz harnesses for parsers. |

> [!TIP]
> For consumers, `MockWebServer` is the recommended test tool: it exercises the genuine network stack rather than mocking the client. Pair with `okhttp-tls` `HeldCertificate` to test HTTPS paths without external CAs.

---

## 11. Integration Patterns

- **Retrofit / higher-level clients.** OkHttp is the standard transport under Retrofit; share one `OkHttpClient` and add cross-cutting concerns (auth, logging, metrics) as interceptors.
- **`java.net` interop.** `okhttp-urlconnection` and `okhttp-java-net-cookiejar` bridge `java.net.Authenticator` and `java.net.CookieHandler`/`CookieManager` into OkHttp.
- **JSON.** Stream `ResponseBody.source()` into Moshi/Gson/kotlinx.serialization rather than buffering with `string()`.
- **Coroutines.** `okhttp-coroutines` `executeAsync()` integrates cleanly with structured concurrency and cancellation.
- **R8/ProGuard.** See `docs/features/r8_proguard.md`; OkHttp ships consumer rules, but verify keep rules for reflective TLS/platform code on Android release builds.

---

## 12. Quick Reference

**Maven coordinates:** `com.squareup.okhttp3:okhttp:5.x` (core) · `:okhttp-bom:5.x` (version alignment).

**Defaults at a glance:**

| Setting | Default |
|---------|---------|
| connect / read / write timeout | 10 s each |
| call timeout | none (0) |
| ping interval | disabled (0) |
| WebSocket close timeout | 60 s |
| protocols | HTTP/2, then HTTP/1.1 |
| connection specs | MODERN_TLS, CLEARTEXT |
| fast fallback (Happy Eyeballs) | enabled |
| retry on connection failure | enabled |
| follow redirects / SSL redirects | enabled |
| dispatcher maxRequests / perHost | 64 / 5 |
| cookie jar | none |
| cache | none |
| authenticator / proxy authenticator | none |
| min WebSocket message to compress | 1024 bytes |

**Minimal client + request:**

```java
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("https://example.com").build();
try (Response response = client.newCall(request).execute()) {
  System.out.println(response.code());
  System.out.println(response.body().string());
}
```

**Production-leaning client:**

```java
OkHttpClient client = new OkHttpClient.Builder()
    .connectTimeout(Duration.ofSeconds(10))
    .callTimeout(Duration.ofSeconds(30))
    .pingInterval(Duration.ofSeconds(30))
    .cache(new Cache(cacheDir, 50L * 1024 * 1024))
    .addInterceptor(authInterceptor)
    .eventListenerFactory(metricsFactory)
    .build();
```

**Operational commands:**

```java
client.connectionPool().evictAll();                 // drop pooled sockets
client.dispatcher().cancelAll();                     // cancel all async calls
client.dispatcher().executorService().shutdown();    // stop accepting calls
client.cache().close();                              // close the cache (teardown only)
```

---

_Generated June 2026 from square/okhttp at 7a35098. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
