Full Code of square/okhttp for AI

master 2ae6e02c2efa cached
783 files
5.7 MB
1.5M tokens
327 symbols
1 requests
Download .txt
Showing preview only (6,117K chars total). Download the full file or copy to clipboard to get everything.
Repository: square/okhttp
Branch: master
Commit: 2ae6e02c2efa
Files: 783
Total size: 5.7 MB

Directory structure:
gitextract_j2sj9obc/

├── .devcontainer/
│   └── devcontainer.json
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── feature_request.md
│   │   └── question.md
│   ├── renovate.json
│   └── workflows/
│       ├── build.yml
│       ├── containers.yml
│       ├── docs.yml
│       └── publish.yml
├── .gitignore
├── .gitmodules
├── .junit.run/
│   └── Not Slow.run.xml
├── .vscode/
│   └── settings.json
├── BUG-BOUNTY.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── android-test/
│   ├── build.gradle.kts
│   └── src/
│       ├── androidDeviceTest/
│       │   ├── README.md
│       │   └── java/
│       │       └── okhttp/
│       │           └── android/
│       │               └── test/
│       │                   ├── OkHttpTest.kt
│       │                   ├── SingleAndroidTest.kt
│       │                   ├── StrictModeTest.kt
│       │                   ├── alpn/
│       │                   │   └── AlpnOverrideTest.kt
│       │                   ├── letsencrypt/
│       │                   │   └── LetsEncryptClientTest.kt
│       │                   └── sni/
│       │                       └── SniOverrideTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   └── res/
│       │       ├── values/
│       │       │   └── strings.xml
│       │       └── xml/
│       │           └── network_security_config.xml
│       └── test/
│           └── kotlin/
│               └── okhttp/
│                   └── android/
│                       └── test/
│                           ├── AndroidLoggingTest.kt
│                           ├── AndroidSocketAdapterTest.kt
│                           ├── BaseOkHttpClientUnitTest.kt
│                           ├── DisabledInitialiserTest.kt
│                           ├── NonRobolectricOkHttpClientTest.kt
│                           ├── RobolectricOkHttpClientTest.kt
│                           └── ShadowDnsResolver.kt
├── android-test-app/
│   ├── build.gradle.kts
│   ├── proguard-rules.pro
│   ├── src/
│   │   ├── androidTest/
│   │   │   └── kotlin/
│   │   │       └── okhttp/
│   │   │           └── android/
│   │   │               └── testapp/
│   │   │                   ├── IdnaTest.kt
│   │   │                   └── PublicSuffixDatabaseTest.kt
│   │   └── main/
│   │       ├── AndroidManifest.xml
│   │       ├── kotlin/
│   │       │   └── okhttp/
│   │       │       └── android/
│   │       │           └── testapp/
│   │       │               ├── MainActivity.kt
│   │       │               ├── MainActivity2.kt
│   │       │               └── TestApplication.kt
│   │       └── res/
│   │           ├── values/
│   │           │   └── strings.xml
│   │           └── xml/
│   │               └── network_security_config.xml
│   └── test-proguard-rules.pro
├── build-logic/
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src/
│       └── main/
│           └── kotlin/
│               ├── AlpnVersions.kt
│               ├── BndBuildAction.kt
│               ├── JavaModules.kt
│               ├── Osgi.kt
│               ├── okhttp.base-conventions.gradle.kts
│               ├── okhttp.dokka-multimodule-conventions.gradle.kts
│               ├── okhttp.jvm-conventions.gradle.kts
│               ├── okhttp.publish-conventions.gradle.kts
│               ├── okhttp.quality-conventions.gradle.kts
│               ├── okhttp.testing-conventions.gradle.kts
│               └── okhttp3/
│                   └── buildsupport/
│                       └── OkHttpBuildUtils.kt
├── build.gradle.kts
├── container-tests/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── containers/
│                       ├── BasicLoomTest.kt
│                       ├── BasicMockServerTest.kt
│                       ├── BasicProxyTest.kt
│                       └── SocksProxyTest.kt
├── deploy_website.sh
├── docs/
│   ├── assets/
│   │   └── css/
│   │       └── app.css
│   ├── changelogs/
│   │   ├── changelog_1x.md
│   │   ├── changelog_2x.md
│   │   ├── changelog_3x.md
│   │   ├── changelog_4x.md
│   │   └── upgrading_to_okhttp_4.md
│   ├── contribute/
│   │   ├── code_of_conduct.md
│   │   ├── concurrency.md
│   │   ├── contributing.md
│   │   └── debug_logging.md
│   ├── features/
│   │   ├── caching.md
│   │   ├── calls.md
│   │   ├── connections.md
│   │   ├── events.md
│   │   ├── https.md
│   │   ├── interceptors.md
│   │   └── r8_proguard.md
│   ├── recipes.md
│   ├── releasing.md
│   ├── security/
│   │   ├── security.md
│   │   ├── security_providers.md
│   │   └── tls_configuration_history.md
│   └── works_with_okhttp.md
├── fuzzing/
│   ├── fuzzingserver-config.json
│   ├── fuzzingserver-expected.txt
│   ├── fuzzingserver-test.sh
│   └── fuzzingserver-update-expected.sh
├── gradle/
│   ├── gradle-daemon-jvm.properties
│   ├── libs.versions.toml
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── maven-tests/
│   ├── .gitignore
│   ├── .mvn/
│   │   ├── jvm.config
│   │   ├── maven.config
│   │   └── wrapper/
│   │       └── maven-wrapper.properties
│   ├── mvnw
│   ├── mvnw.cmd
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── squareup/
│       │               └── okhttp3/
│       │                   └── maventest/
│       │                       └── SampleHttpClient.java
│       └── test/
│           └── java/
│               └── com/
│                   └── squareup/
│                       └── okhttp3/
│                           └── maventest/
│                               └── AppTest.java
├── mkdocs.yml
├── mockwebserver/
│   ├── Module.md
│   ├── README.md
│   ├── api/
│   │   └── mockwebserver3.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── mockwebserver3/
│       │           ├── Dispatcher.kt
│       │           ├── MockResponse.kt
│       │           ├── MockResponseBody.kt
│       │           ├── MockWebServer.kt
│       │           ├── PushPromise.kt
│       │           ├── QueueDispatcher.kt
│       │           ├── RecordedRequest.kt
│       │           ├── SocketEffect.kt
│       │           ├── SocketHandler.kt
│       │           └── internal/
│       │               ├── BufferMockResponseBody.kt
│       │               ├── MockWebServerSocket.kt
│       │               ├── RecordedRequestFactory.kt
│       │               ├── ThrottledSink.kt
│       │               └── TriggerSink.kt
│       └── test/
│           └── java/
│               └── mockwebserver3/
│                   ├── CustomDispatcherTest.kt
│                   ├── MockResponseSniTest.kt
│                   ├── MockWebServerTest.kt
│                   ├── RecordedRequestTest.kt
│                   └── internal/
│                       └── http2/
│                           └── Http2Server.kt
├── mockwebserver-deprecated/
│   ├── api/
│   │   └── mockwebserver.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── mockwebserver/
│       │               ├── DeprecationBridge.kt
│       │               ├── Dispatcher.kt
│       │               ├── MockResponse.kt
│       │               ├── MockWebServer.kt
│       │               ├── PushPromise.kt
│       │               ├── QueueDispatcher.kt
│       │               ├── RecordedRequest.kt
│       │               └── SocketPolicy.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── mockwebserver/
│                       ├── KotlinSourceModernTest.kt
│                       └── MockWebServerTest.kt
├── mockwebserver-junit4/
│   ├── README.md
│   ├── api/
│   │   └── mockwebserver3-junit4.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── mockwebserver3/
│       │           └── junit4/
│       │               └── MockWebServerRule.kt
│       └── test/
│           └── java/
│               └── mockwebserver3/
│                   └── junit4/
│                       └── MockWebServerRuleTest.kt
├── mockwebserver-junit5/
│   ├── README.md
│   ├── api/
│   │   └── mockwebserver3-junit5.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── mockwebserver3/
│       │           └── junit5/
│       │               ├── StartStop.kt
│       │               └── internal/
│       │                   └── StartStopExtension.kt
│       └── test/
│           └── java/
│               └── mockwebserver3/
│                   └── junit5/
│                       └── StartStopTest.kt
├── module-tests/
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── okhttp3/
│       │           └── modules/
│       │               ├── Main.java
│       │               └── OkHttpCaller.java
│       └── test/
│           └── java/
│               ├── module-info.java
│               └── okhttp3/
│                   └── modules/
│                       └── test/
│                           └── JavaModuleTest.java
├── native-image-tests/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       └── test/
│           ├── kotlin/
│           │   └── okhttp3/
│           │       └── nativeimage/
│           │           ├── PublicSuffixDatabaseTest.kt
│           │           ├── SampleTest.kt
│           │           └── WithArgumentSourceTest.kt
│           └── resources/
│               └── META-INF/
│                   └── native-image/
│                       └── okhttp/
│                           └── nit/
│                               └── resource-config.json
├── okcurl/
│   ├── README.md
│   ├── build.gradle.kts
│   ├── okcurl
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       └── curl/
│       │   │           ├── Main.kt
│       │   │           ├── MainCommandLine.kt
│       │   │           ├── internal/
│       │   │           │   └── -MainCommon.kt
│       │   │           └── logging/
│       │   │               ├── LoggingUtil.kt
│       │   │               ├── MessageFormatter.kt
│       │   │               └── OneLineLogFormat.kt
│       │   ├── resources/
│       │   │   └── META-INF/
│       │   │       └── native-image/
│       │   │           └── okhttp3/
│       │   │               └── okcurl/
│       │   │                   ├── reflect-config.json
│       │   │                   └── resource-config.json
│       │   └── resources-templates/
│       │       └── okcurl-version.properties
│       └── test/
│           └── kotlin/
│               └── okhttp3/
│                   └── curl/
│                       └── MainTest.kt
├── okhttp/
│   ├── Module.md
│   ├── api/
│   │   ├── android/
│   │   │   └── okhttp.api
│   │   └── jvm/
│   │       └── okhttp.api
│   ├── build.gradle.kts
│   ├── okhttp3.pro
│   └── src/
│       ├── androidHostTest/
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       └── internal/
│       │   │           └── publicsuffix/
│       │   │               └── PublicSuffixTesting.android.kt
│       │   └── resources/
│       │       └── okhttp3/
│       │           └── robolectric.properties
│       ├── androidMain/
│       │   ├── AndroidManifest.xml
│       │   ├── assets/
│       │   │   └── PublicSuffixDatabase.list
│       │   ├── baseline-prof.txt
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           ├── OkHttp.android.kt
│       │           └── internal/
│       │               ├── platform/
│       │               │   ├── Android10Platform.kt
│       │               │   ├── AndroidPlatform.kt
│       │               │   ├── ContextAwarePlatform.kt
│       │               │   ├── PlatformInitializer.kt
│       │               │   ├── PlatformRegistry.kt
│       │               │   └── android/
│       │               │       ├── Android10SocketAdapter.kt
│       │               │       ├── AndroidCertificateChainCleaner.kt
│       │               │       ├── AndroidLog.kt
│       │               │       ├── AndroidSocketAdapter.kt
│       │               │       ├── BouncyCastleSocketAdapter.kt
│       │               │       ├── ConscryptSocketAdapter.kt
│       │               │       ├── DeferredSocketAdapter.kt
│       │               │       ├── SocketAdapter.kt
│       │               │       └── StandardAndroidSocketAdapter.kt
│       │               └── publicsuffix/
│       │                   ├── AssetPublicSuffixList.kt
│       │                   └── PublicSuffixList.android.kt
│       ├── commonJvmAndroid/
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       ├── Address.kt
│       │   │       ├── Authenticator.kt
│       │   │       ├── Cache.kt
│       │   │       ├── CacheControl.kt
│       │   │       ├── Call.kt
│       │   │       ├── Callback.kt
│       │   │       ├── CertificatePinner.kt
│       │   │       ├── Challenge.kt
│       │   │       ├── CipherSuite.kt
│       │   │       ├── CompressionInterceptor.kt
│       │   │       ├── Connection.kt
│       │   │       ├── ConnectionPool.kt
│       │   │       ├── ConnectionSpec.kt
│       │   │       ├── Cookie.kt
│       │   │       ├── CookieJar.kt
│       │   │       ├── Credentials.kt
│       │   │       ├── Dispatcher.kt
│       │   │       ├── Dns.kt
│       │   │       ├── EventListener.kt
│       │   │       ├── FormBody.kt
│       │   │       ├── Gzip.kt
│       │   │       ├── Handshake.kt
│       │   │       ├── Headers.kt
│       │   │       ├── HttpUrl.kt
│       │   │       ├── Interceptor.kt
│       │   │       ├── MediaType.kt
│       │   │       ├── MultipartBody.kt
│       │   │       ├── MultipartReader.kt
│       │   │       ├── OkHttp.kt
│       │   │       ├── OkHttpClient.kt
│       │   │       ├── Protocol.kt
│       │   │       ├── Request.kt
│       │   │       ├── RequestBody.kt
│       │   │       ├── Response.kt
│       │   │       ├── ResponseBody.kt
│       │   │       ├── Route.kt
│       │   │       ├── TlsVersion.kt
│       │   │       ├── TrailersSource.kt
│       │   │       ├── WebSocket.kt
│       │   │       ├── WebSocketListener.kt
│       │   │       └── internal/
│       │   │           ├── -CacheControlCommon.kt
│       │   │           ├── -HeadersCommon.kt
│       │   │           ├── -HostnamesCommon.kt
│       │   │           ├── -NormalizeJvm.kt
│       │   │           ├── -UtilCommon.kt
│       │   │           ├── -UtilJvm.kt
│       │   │           ├── IsProbablyUtf8.kt
│       │   │           ├── NativeImageTestsAccessors.kt
│       │   │           ├── SuppressSignatureCheck.kt
│       │   │           ├── Tags.kt
│       │   │           ├── UnreadableResponseBody.kt
│       │   │           ├── authenticator/
│       │   │           │   └── JavaNetAuthenticator.kt
│       │   │           ├── cache/
│       │   │           │   ├── CacheInterceptor.kt
│       │   │           │   ├── CacheRequest.kt
│       │   │           │   ├── CacheStrategy.kt
│       │   │           │   ├── DiskLruCache.kt
│       │   │           │   └── FaultHidingSink.kt
│       │   │           ├── concurrent/
│       │   │           │   ├── Lockable.kt
│       │   │           │   ├── Task.kt
│       │   │           │   ├── TaskLogger.kt
│       │   │           │   ├── TaskQueue.kt
│       │   │           │   └── TaskRunner.kt
│       │   │           ├── connection/
│       │   │           │   ├── AddressPolicy.kt
│       │   │           │   ├── BufferedSocket.kt
│       │   │           │   ├── ConnectInterceptor.kt
│       │   │           │   ├── ConnectPlan.kt
│       │   │           │   ├── ConnectionListener.kt
│       │   │           │   ├── Exchange.kt
│       │   │           │   ├── ExchangeFinder.kt
│       │   │           │   ├── FailedPlan.kt
│       │   │           │   ├── FastFallbackExchangeFinder.kt
│       │   │           │   ├── ForceConnectRoutePlanner.kt
│       │   │           │   ├── InetAddressOrder.kt
│       │   │           │   ├── RealCall.kt
│       │   │           │   ├── RealConnection.kt
│       │   │           │   ├── RealConnectionPool.kt
│       │   │           │   ├── RealRoutePlanner.kt
│       │   │           │   ├── RetryTlsHandshake.kt
│       │   │           │   ├── ReusePlan.kt
│       │   │           │   ├── RouteDatabase.kt
│       │   │           │   ├── RoutePlanner.kt
│       │   │           │   ├── RouteSelector.kt
│       │   │           │   └── SequentialExchangeFinder.kt
│       │   │           ├── http/
│       │   │           │   ├── BridgeInterceptor.kt
│       │   │           │   ├── CallServerInterceptor.kt
│       │   │           │   ├── DateFormatting.kt
│       │   │           │   ├── ExchangeCodec.kt
│       │   │           │   ├── GzipRequestBody.kt
│       │   │           │   ├── HttpHeaders.kt
│       │   │           │   ├── HttpMethod.kt
│       │   │           │   ├── HttpStatusCodes.kt
│       │   │           │   ├── RealInterceptorChain.kt
│       │   │           │   ├── RealResponseBody.kt
│       │   │           │   ├── RequestLine.kt
│       │   │           │   ├── RetryAndFollowUpInterceptor.kt
│       │   │           │   └── StatusLine.kt
│       │   │           ├── http1/
│       │   │           │   ├── HeadersReader.kt
│       │   │           │   └── Http1ExchangeCodec.kt
│       │   │           ├── http2/
│       │   │           │   ├── ConnectionShutdownException.kt
│       │   │           │   ├── ErrorCode.kt
│       │   │           │   ├── FlowControlListener.kt
│       │   │           │   ├── Header.kt
│       │   │           │   ├── Hpack.kt
│       │   │           │   ├── Http2.kt
│       │   │           │   ├── Http2Connection.kt
│       │   │           │   ├── Http2ExchangeCodec.kt
│       │   │           │   ├── Http2Reader.kt
│       │   │           │   ├── Http2Stream.kt
│       │   │           │   ├── Http2Writer.kt
│       │   │           │   ├── Huffman.kt
│       │   │           │   ├── PushObserver.kt
│       │   │           │   ├── Settings.kt
│       │   │           │   ├── StreamResetException.kt
│       │   │           │   └── flowcontrol/
│       │   │           │       └── WindowCounter.kt
│       │   │           ├── idn/
│       │   │           │   ├── IdnaMappingTable.kt
│       │   │           │   └── Punycode.kt
│       │   │           ├── internal.kt
│       │   │           ├── platform/
│       │   │           │   ├── Jdk9Platform.kt
│       │   │           │   ├── Platform.kt
│       │   │           │   └── PlatformRegistry.kt
│       │   │           ├── proxy/
│       │   │           │   └── NullProxySelector.kt
│       │   │           ├── publicsuffix/
│       │   │           │   ├── BasePublicSuffixList.kt
│       │   │           │   ├── PublicSuffixDatabase.kt
│       │   │           │   ├── PublicSuffixList.kt
│       │   │           │   └── ResourcePublicSuffixList.kt
│       │   │           ├── tls/
│       │   │           │   ├── BasicCertificateChainCleaner.kt
│       │   │           │   ├── BasicTrustRootIndex.kt
│       │   │           │   ├── CertificateChainCleaner.kt
│       │   │           │   ├── OkHostnameVerifier.kt
│       │   │           │   └── TrustRootIndex.kt
│       │   │           ├── url/
│       │   │           │   └── -Url.kt
│       │   │           └── ws/
│       │   │               ├── MessageDeflater.kt
│       │   │               ├── MessageInflater.kt
│       │   │               ├── RealWebSocket.kt
│       │   │               ├── WebSocketExtensions.kt
│       │   │               ├── WebSocketProtocol.kt
│       │   │               ├── WebSocketReader.kt
│       │   │               └── WebSocketWriter.kt
│       │   └── kotlinTemplates/
│       │       └── okhttp3/
│       │           └── internal/
│       │               └── -InternalVersion.kt
│       ├── commonTest/
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           ├── CompressionInterceptorTest.kt
│       │           ├── OkHttpTest.kt
│       │           └── internal/
│       │               ├── IsProbablyUtf8Test.kt
│       │               └── publicsuffix/
│       │                   ├── ConfiguredPublicSuffixDatabaseTest.kt
│       │                   ├── ConfiguredPublicSuffixList.kt
│       │                   ├── PublicSuffixDatabaseTest.kt
│       │                   └── PublicSuffixTesting.kt
│       ├── jvmMain/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       ├── OkHttp.jvm.kt
│       │   │       └── internal/
│       │   │           ├── graal/
│       │   │           │   ├── GraalSvm.kt
│       │   │           │   └── OkHttpFeature.kt
│       │   │           ├── platform/
│       │   │           │   ├── BouncyCastlePlatform.kt
│       │   │           │   ├── ConscryptPlatform.kt
│       │   │           │   ├── Jdk8WithJettyBootPlatform.kt
│       │   │           │   ├── OpenJSSEPlatform.kt
│       │   │           │   └── PlatformRegistry.kt
│       │   │           └── publicsuffix/
│       │   │               └── PublicSuffixList.jvm.kt
│       │   └── resources/
│       │       ├── META-INF/
│       │       │   └── native-image/
│       │       │       └── okhttp/
│       │       │           └── okhttp/
│       │       │               ├── native-image.properties
│       │       │               ├── reflect-config.json
│       │       │               └── resource-config.json
│       │       └── okhttp3/
│       │           └── internal/
│       │               └── publicsuffix/
│       │                   └── PublicSuffixDatabase.list
│       ├── jvmTest/
│       │   ├── java/
│       │   │   └── okhttp3/
│       │   │       └── CallJavaTest.java
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       ├── AddressTest.kt
│       │   │       ├── AutobahnTester.kt
│       │   │       ├── BouncyCastleTest.kt
│       │   │       ├── CacheControlJvmTest.kt
│       │   │       ├── CacheControlTest.kt
│       │   │       ├── CacheCorruptionTest.kt
│       │   │       ├── CacheTest.kt
│       │   │       ├── CallHandshakeTest.kt
│       │   │       ├── CallKotlinTest.kt
│       │   │       ├── CallLimitsTest.kt
│       │   │       ├── CallTagsTest.kt
│       │   │       ├── CallTest.kt
│       │   │       ├── CertificateChainCleanerTest.kt
│       │   │       ├── CertificatePinnerKotlinTest.kt
│       │   │       ├── CertificatePinnerTest.kt
│       │   │       ├── ChannelSocketFactory.kt
│       │   │       ├── CipherSuiteTest.kt
│       │   │       ├── CommonRequestBodyTest.kt
│       │   │       ├── ConnectionCoalescingTest.kt
│       │   │       ├── ConnectionListenerTest.kt
│       │   │       ├── ConnectionReuseTest.kt
│       │   │       ├── ConnectionSpecTest.kt
│       │   │       ├── ConscryptTest.kt
│       │   │       ├── CookieTest.kt
│       │   │       ├── CookiesTest.kt
│       │   │       ├── CorrettoTest.kt
│       │   │       ├── DispatcherCleanupTest.kt
│       │   │       ├── DispatcherTest.kt
│       │   │       ├── DuplexTest.kt
│       │   │       ├── EventListenerTest.kt
│       │   │       ├── FakeRoutePlanner.kt
│       │   │       ├── FallbackTestClientSocketFactory.kt
│       │   │       ├── FastFallbackTest.kt
│       │   │       ├── FormBodyTest.kt
│       │   │       ├── HandshakeTest.kt
│       │   │       ├── HeadersChallengesTest.kt
│       │   │       ├── HeadersJvmTest.kt
│       │   │       ├── HeadersKotlinTest.kt
│       │   │       ├── HeadersRequestTest.kt
│       │   │       ├── HeadersTest.kt
│       │   │       ├── HttpUrlJvmTest.kt
│       │   │       ├── HttpUrlTest.kt
│       │   │       ├── InsecureForHostTest.kt
│       │   │       ├── InterceptorOverridesTest.kt
│       │   │       ├── InterceptorTest.kt
│       │   │       ├── JSSETest.kt
│       │   │       ├── KotlinDeprecationErrorTest.kt
│       │   │       ├── KotlinSourceModernTest.kt
│       │   │       ├── LoomTest.kt
│       │   │       ├── MediaTypeGetTest.kt
│       │   │       ├── MediaTypeJvmTest.kt
│       │   │       ├── MediaTypeTest.kt
│       │   │       ├── MultipartBodyTest.kt
│       │   │       ├── MultipartReaderTest.kt
│       │   │       ├── OkHttpClientTest.kt
│       │   │       ├── OpenJSSETest.kt
│       │   │       ├── ProtocolTest.kt
│       │   │       ├── PublicInternalApiTest.kt
│       │   │       ├── RecordedResponse.kt
│       │   │       ├── RecordingCallback.kt
│       │   │       ├── RecordingExecutor.kt
│       │   │       ├── RequestBodyTest.kt
│       │   │       ├── RequestCommonTest.kt
│       │   │       ├── RequestTest.kt
│       │   │       ├── ResponseBodyJvmTest.kt
│       │   │       ├── ResponseBodyTest.kt
│       │   │       ├── ResponseCommonTest.kt
│       │   │       ├── ResponseJvmTest.kt
│       │   │       ├── RouteFailureTest.kt
│       │   │       ├── ServerTruncatesRequestTest.kt
│       │   │       ├── SessionReuseTest.kt
│       │   │       ├── SocketChannelTest.kt
│       │   │       ├── SocksProxy.kt
│       │   │       ├── SocksProxyTest.kt
│       │   │       ├── TestLogHandler.kt
│       │   │       ├── TestTls13Request.kt
│       │   │       ├── TrailersTest.kt
│       │   │       ├── URLConnectionTest.kt
│       │   │       ├── UrlComponentEncodingTester.kt
│       │   │       ├── UrlComponentEncodingTesterJvm.kt
│       │   │       ├── WebPlatformToAsciiData.kt
│       │   │       ├── WebPlatformToAsciiTest.kt
│       │   │       ├── WebPlatformUrlTest.kt
│       │   │       ├── WebPlatformUrlTestData.kt
│       │   │       ├── WholeOperationTimeoutTest.kt
│       │   │       └── internal/
│       │   │           ├── DoubleInetAddressDns.kt
│       │   │           ├── HostnamesTest.kt
│       │   │           ├── RecordingAuthenticator.kt
│       │   │           ├── TagsTest.kt
│       │   │           ├── UtilTest.kt
│       │   │           ├── authenticator/
│       │   │           │   └── JavaNetAuthenticatorTest.kt
│       │   │           ├── cache/
│       │   │           │   └── DiskLruCacheTest.kt
│       │   │           ├── concurrent/
│       │   │           │   ├── TaskLoggerTest.kt
│       │   │           │   ├── TaskRunnerRealBackendTest.kt
│       │   │           │   └── TaskRunnerTest.kt
│       │   │           ├── connection/
│       │   │           │   ├── ConnectionPoolTest.kt
│       │   │           │   ├── FastFallbackExchangeFinderTest.kt
│       │   │           │   ├── InetAddressOrderTest.kt
│       │   │           │   ├── RetryConnectionTest.kt
│       │   │           │   └── RouteSelectorTest.kt
│       │   │           ├── http/
│       │   │           │   ├── CancelTest.kt
│       │   │           │   ├── ExternalHttp2Example.kt
│       │   │           │   ├── HttpDateTest.kt
│       │   │           │   ├── HttpUpgradesTest.kt
│       │   │           │   ├── SocketFailureTest.kt
│       │   │           │   ├── StatusLineTest.kt
│       │   │           │   └── ThreadInterruptTest.kt
│       │   │           ├── http2/
│       │   │           │   ├── BaseTestHandler.kt
│       │   │           │   ├── FrameLogTest.kt
│       │   │           │   ├── HpackTest.kt
│       │   │           │   ├── Http2ConnectionTest.kt
│       │   │           │   ├── Http2Test.kt
│       │   │           │   ├── HttpOverHttp2Test.kt
│       │   │           │   ├── HuffmanTest.kt
│       │   │           │   ├── MockHttp2Peer.kt
│       │   │           │   └── SettingsTest.kt
│       │   │           ├── idn/
│       │   │           │   ├── IdnaMappingTableTest.kt
│       │   │           │   └── PunycodeTest.kt
│       │   │           ├── io/
│       │   │           │   └── FaultyFileSystem.kt
│       │   │           ├── platform/
│       │   │           │   ├── Jdk8WithJettyBootPlatformTest.kt
│       │   │           │   ├── Jdk9PlatformTest.kt
│       │   │           │   └── PlatformTest.kt
│       │   │           ├── publicsuffix/
│       │   │           │   ├── PublicSuffixListGenerator.kt
│       │   │           │   └── PublicSuffixTesting.jvm.kt
│       │   │           ├── tls/
│       │   │           │   ├── CertificatePinnerChainValidationTest.kt
│       │   │           │   ├── ClientAuthTest.kt
│       │   │           │   └── HostnameVerifierTest.kt
│       │   │           └── ws/
│       │   │               ├── MessageDeflaterInflaterTest.kt
│       │   │               ├── RealWebSocketTest.kt
│       │   │               ├── WebSocketExtensionsTest.kt
│       │   │               ├── WebSocketHttpTest.kt
│       │   │               ├── WebSocketReaderTest.kt
│       │   │               ├── WebSocketRecorder.kt
│       │   │               └── WebSocketWriterTest.kt
│       │   └── resources/
│       │       ├── okhttp3/
│       │       │   └── internal/
│       │       │       └── publicsuffix/
│       │       │           └── NOTICE
│       │       ├── web-platform-test-toascii.json
│       │       └── web-platform-test-urltestdata.txt
│       └── main/
│           └── resources/
│               └── META-INF/
│                   └── native-image/
│                       └── okhttp/
│                           └── okhttp/
│                               └── native-image.properties
├── okhttp-bom/
│   └── build.gradle.kts
├── okhttp-brotli/
│   ├── README.md
│   ├── api/
│   │   └── okhttp-brotli.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── brotli/
│       │               ├── Brotli.kt
│       │               └── BrotliInterceptor.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── brotli/
│                       ├── BrotliInterceptorTest.kt
│                       └── BrotliTestMain.kt
├── okhttp-coroutines/
│   ├── Module.md
│   ├── README.md
│   ├── api/
│   │   └── okhttp-coroutines.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── coroutines/
│       │               └── ExecuteAsync.kt
│       └── test/
│           └── kotlin/
│               └── okhttp3/
│                   └── coroutines/
│                       └── ExecuteAsyncTest.kt
├── okhttp-dnsoverhttps/
│   ├── README.md
│   ├── api/
│   │   └── okhttp-dnsoverhttps.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── dnsoverhttps/
│       │               ├── BootstrapDns.kt
│       │               ├── DnsOverHttps.kt
│       │               └── DnsRecordCodec.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── dnsoverhttps/
│                       ├── DnsOverHttpsTest.kt
│                       ├── DnsRecordCodecTest.kt
│                       ├── DohProviders.kt
│                       └── TestDohMain.kt
├── okhttp-hpacktests/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── internal/
│                       └── http2/
│                           ├── HpackDecodeInteropTest.kt
│                           ├── HpackDecodeTestBase.kt
│                           ├── HpackRoundTripTest.kt
│                           └── hpackjson/
│                               ├── Case.kt
│                               ├── HpackJsonUtil.kt
│                               └── Story.kt
├── okhttp-idna-mapping-table/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       └── internal/
│       │   │           └── idn/
│       │   │               ├── GenerateIdnaMappingTableCode.kt
│       │   │               ├── IdnaMappingTableData.kt
│       │   │               ├── MappedRange.kt
│       │   │               ├── MappingTables.kt
│       │   │               └── SimpleIdnaMappingTable.kt
│       │   └── resources/
│       │       └── okhttp3/
│       │           └── internal/
│       │               └── idna/
│       │                   └── IdnaMappingTable.txt
│       └── test/
│           └── kotlin/
│               └── okhttp3/
│                   └── internal/
│                       └── idn/
│                           └── MappingTablesTest.kt
├── okhttp-java-net-cookiejar/
│   ├── README.md
│   ├── api/
│   │   └── okhttp-java-net-cookiejar.api
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           ├── java9/
│           │   └── module-info.java
│           └── kotlin/
│               └── okhttp3/
│                   └── java/
│                       └── net/
│                           └── cookiejar/
│                               └── JavaNetCookieJar.kt
├── okhttp-logging-interceptor/
│   ├── Module.md
│   ├── README.md
│   ├── api/
│   │   └── logging-interceptor.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── logging/
│       │               ├── HttpLoggingInterceptor.kt
│       │               └── LoggingEventListener.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── logging/
│                       ├── HttpLoggingInterceptorTest.kt
│                       └── LoggingEventListenerTest.kt
├── okhttp-osgi-tests/
│   ├── build.gradle.kts
│   └── src/
│       └── test/
│           └── kotlin/
│               └── okhttp3/
│                   └── osgi/
│                       └── OsgiTest.kt
├── okhttp-sse/
│   ├── Module.md
│   ├── README.md
│   ├── api/
│   │   └── okhttp-sse.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── sse/
│       │               ├── EventSource.kt
│       │               ├── EventSourceListener.kt
│       │               ├── EventSources.kt
│       │               └── internal/
│       │                   ├── RealEventSource.kt
│       │                   └── ServerSentEventReader.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── sse/
│                       └── internal/
│                           ├── Event.kt
│                           ├── EventSourceHttpTest.kt
│                           ├── EventSourceRecorder.kt
│                           ├── EventSourcesHttpTest.kt
│                           └── ServerSentEventIteratorTest.kt
├── okhttp-testing-support/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       ├── CallEvent.kt
│       │   │       ├── ClientRuleEventListener.kt
│       │   │       ├── ConnectionEvent.kt
│       │   │       ├── DelegatingSSLSession.kt
│       │   │       ├── DelegatingSSLSocket.kt
│       │   │       ├── DelegatingSSLSocketFactory.kt
│       │   │       ├── DelegatingServerSocketFactory.kt
│       │   │       ├── DelegatingSocketFactory.kt
│       │   │       ├── EventListenerAdapter.kt
│       │   │       ├── EventListenerRelay.kt
│       │   │       ├── EventRecorder.kt
│       │   │       ├── FailingCall.kt
│       │   │       ├── FakeDns.kt
│       │   │       ├── FakeProxySelector.kt
│       │   │       ├── FakeSSLSession.kt
│       │   │       ├── ForwardingRequestBody.kt
│       │   │       ├── ForwardingResponseBody.kt
│       │   │       ├── JsseDebugLogging.kt
│       │   │       ├── OkHttpClientTestRule.kt
│       │   │       ├── OkHttpDebugLogging.kt
│       │   │       ├── RecordingConnectionListener.kt
│       │   │       ├── RecordingCookieJar.kt
│       │   │       ├── RecordingHostnameVerifier.kt
│       │   │       ├── SimpleProvider.kt
│       │   │       ├── SpecificHostSocketFactory.kt
│       │   │       ├── TestUtilCommon.kt
│       │   │       ├── TestUtilJvm.kt
│       │   │       ├── TestValueFactory.kt
│       │   │       ├── UppercaseRequestInterceptor.kt
│       │   │       ├── UppercaseResponseInterceptor.kt
│       │   │       ├── internal/
│       │   │       │   ├── RecordingOkAuthenticator.kt
│       │   │       │   ├── concurrent/
│       │   │       │   │   └── TaskFaker.kt
│       │   │       │   ├── duplex/
│       │   │       │   │   ├── AsyncRequestBody.kt
│       │   │       │   │   └── MockSocketHandler.kt
│       │   │       │   └── http/
│       │   │       │       └── RecordingProxySelector.kt
│       │   │       ├── okio/
│       │   │       │   └── LoggingFilesystem.kt
│       │   │       └── testing/
│       │   │           ├── Flaky.kt
│       │   │           ├── PlatformRule.kt
│       │   │           └── PlatformVersion.kt
│       │   └── resources/
│       │       └── META-INF/
│       │           └── proguard/
│       │               └── okhttp3.pro
│       └── test/
│           └── kotlin/
│               └── okhttp3/
│                   ├── OkHttpClientTestRuleTest.kt
│                   └── testing/
│                       └── PlatformRuleTest.kt
├── okhttp-tls/
│   ├── Module.md
│   ├── README.md
│   ├── api/
│   │   └── okhttp-tls.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── tls/
│       │               ├── Certificates.kt
│       │               ├── HandshakeCertificates.kt
│       │               ├── HeldCertificate.kt
│       │               └── internal/
│       │                   ├── InsecureAndroidTrustManager.kt
│       │                   ├── InsecureExtendedTrustManager.kt
│       │                   ├── TlsUtil.kt
│       │                   └── der/
│       │                       ├── Adapters.kt
│       │                       ├── AnyValue.kt
│       │                       ├── BasicDerAdapter.kt
│       │                       ├── BitString.kt
│       │                       ├── Certificate.kt
│       │                       ├── CertificateAdapters.kt
│       │                       ├── DerAdapter.kt
│       │                       ├── DerHeader.kt
│       │                       ├── DerReader.kt
│       │                       ├── DerWriter.kt
│       │                       └── ObjectIdentifiers.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── tls/
│                       ├── CertificatesJavaTest.java
│                       ├── CertificatesTest.kt
│                       ├── HandshakeCertificatesTest.kt
│                       ├── HeldCertificateTest.kt
│                       └── internal/
│                           └── der/
│                               ├── DerCertificatesTest.kt
│                               └── DerTest.kt
├── okhttp-urlconnection/
│   ├── README.md
│   ├── api/
│   │   └── okhttp-urlconnection.api
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           ├── java9/
│           │   └── module-info.java
│           └── kotlin/
│               └── okhttp3/
│                   ├── JavaNetAuthenticator.kt
│                   └── JavaNetCookieJar.kt
├── okhttp-zstd/
│   ├── README.md
│   ├── api/
│   │   └── okhttp-zstd.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── zstd/
│       │               └── Zstd.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── zstd/
│                       ├── ZstdInterceptorJavaTest.java
│                       ├── ZstdInterceptorTest.kt
│                       └── ZstdTestMain.kt
├── regression-test/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── okhttp/
│       │           └── regression/
│       │               ├── IssueReproductionTest.java
│       │               ├── LetsEncryptTest.java
│       │               └── compare/
│       │                   ├── AndroidHttpEngineTest.kt
│       │                   ├── ApacheHttpClientHttp2Test.kt
│       │                   ├── ApacheHttpClientTest.kt
│       │                   └── OkHttpClientTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           └── res/
│               ├── values/
│               │   └── strings.xml
│               └── xml/
│                   └── network_security_config.xml
├── samples/
│   ├── compare/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── test/
│   │           └── kotlin/
│   │               └── okhttp3/
│   │                   └── compare/
│   │                       ├── ApacheHttpClientTest.kt
│   │                       ├── JavaHttpClientTest.kt
│   │                       ├── JettyHttpClientTest.kt
│   │                       └── OkHttpClientTest.kt
│   ├── crawler/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── okhttp3/
│   │                   └── sample/
│   │                       └── Crawler.java
│   ├── guide/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       └── okhttp3/
│   │       │           ├── guide/
│   │       │           │   ├── GetExample.java
│   │       │           │   └── PostExample.java
│   │       │           └── recipes/
│   │       │               ├── AccessHeaders.java
│   │       │               ├── AsynchronousGet.java
│   │       │               ├── Authenticate.java
│   │       │               ├── CacheResponse.java
│   │       │               ├── CancelCall.java
│   │       │               ├── CertificatePinning.java
│   │       │               ├── CheckHandshake.java
│   │       │               ├── ConfigureTimeouts.java
│   │       │               ├── CurrentDateHeader.java
│   │       │               ├── CustomCipherSuites.java
│   │       │               ├── CustomTrust.java
│   │       │               ├── HttpsServer.java
│   │       │               ├── LoggingInterceptors.java
│   │       │               ├── ParseResponseWithMoshi.java
│   │       │               ├── PerCallSettings.java
│   │       │               ├── PostFile.java
│   │       │               ├── PostForm.java
│   │       │               ├── PostMultipart.java
│   │       │               ├── PostStreaming.java
│   │       │               ├── PostStreamingWithPipe.java
│   │       │               ├── PostString.java
│   │       │               ├── PreemptiveAuth.java
│   │       │               ├── PrintEvents.java
│   │       │               ├── PrintEventsNonConcurrent.java
│   │       │               ├── Progress.java
│   │       │               ├── RequestBodyCompression.java
│   │       │               ├── RewriteResponseCacheControl.java
│   │       │               ├── SynchronousGet.java
│   │       │               ├── UploadProgress.java
│   │       │               ├── WebSocketEcho.java
│   │       │               └── kt/
│   │       │                   ├── AccessHeaders.kt
│   │       │                   ├── AsynchronousGet.kt
│   │       │                   ├── Authenticate.kt
│   │       │                   ├── CacheResponse.kt
│   │       │                   ├── CancelCall.kt
│   │       │                   ├── CertificatePinning.kt
│   │       │                   ├── ConfigureTimeouts.kt
│   │       │                   ├── CustomTrust.kt
│   │       │                   ├── DevServer.kt
│   │       │                   ├── ParseResponseWithMoshi.kt
│   │       │                   ├── PerCallSettings.kt
│   │       │                   ├── PostFile.kt
│   │       │                   ├── PostForm.kt
│   │       │                   ├── PostMultipart.kt
│   │       │                   ├── PostPath.kt
│   │       │                   ├── PostStreaming.kt
│   │       │                   ├── PostString.kt
│   │       │                   ├── SynchronousGet.kt
│   │       │                   ├── UploadProgress.kt
│   │       │                   ├── WiresharkExample.kt
│   │       │                   └── YubikeyClientAuth.kt
│   │       └── test/
│   │           └── kotlin/
│   │               └── okhttp3/
│   │                   └── AllMainsTest.kt
│   ├── simple-client/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── okhttp3/
│   │                   └── sample/
│   │                       └── OkHttpContributors.java
│   ├── slack/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── okhttp3/
│   │                   └── slack/
│   │                       ├── OAuthSession.java
│   │                       ├── OAuthSessionFactory.java
│   │                       ├── RtmSession.java
│   │                       ├── RtmStartResponse.java
│   │                       ├── SlackApi.java
│   │                       └── SlackClient.java
│   ├── static-server/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── okhttp3/
│   │                   └── sample/
│   │                       └── SampleServer.java
│   ├── tlssurvey/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           ├── kotlin/
│   │           │   └── okhttp3/
│   │           │       └── survey/
│   │           │           ├── CipherSuiteSurvey.kt
│   │           │           ├── Clients.kt
│   │           │           ├── Iana.kt
│   │           │           ├── RunSurvey.kt
│   │           │           ├── ssllabs/
│   │           │           │   ├── SslLabsApi.kt
│   │           │           │   ├── SslLabsClient.kt
│   │           │           │   └── UserAgentCapabilities.kt
│   │           │           └── types/
│   │           │               ├── Client.kt
│   │           │               └── SuiteId.kt
│   │           └── resources/
│   │               ├── okhttp_3.11.txt
│   │               ├── okhttp_3.13.txt
│   │               ├── okhttp_3.14.txt
│   │               ├── okhttp_3.9.txt
│   │               └── okhttp_4.10.txt
│   └── unixdomainsockets/
│       ├── build.gradle.kts
│       └── src/
│           └── main/
│               └── java/
│                   └── okhttp3/
│                       └── unixdomainsockets/
│                           ├── ClientAndServer.java
│                           ├── TunnelingUnixSocket.java
│                           ├── UnixDomainServerSocketFactory.java
│                           └── UnixDomainSocketFactory.java
├── settings.gradle.kts
└── test_docs.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .devcontainer/devcontainer.json
================================================
{
  "image": "mcr.microsoft.com/devcontainers/java:21-bookworm",
  "features": {
      "ghcr.io/devcontainers/features/java:1": {
          "version": "17"
      }
  },
  "customizations": {
      "vscode": {
          "settings": {
              "java.server.launchMode": "Standard"
          },
          "extensions": [
              "vscjava.vscode-java-pack",
              "vscjava.vscode-gradle"
          ]
      }
  }
}


================================================
FILE: .editorconfig
================================================
root = true

[*]
indent_size = 2
ij_continuation_indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{kt, kts}]
ij_kotlin_imports_layout = *


================================================
FILE: .gitattributes
================================================
* text=auto eol=lf

*.bat text eol=crlf
*.jar binary

================================================
FILE: .github/CONTRIBUTING.md
================================================
Contributing
============

If you would like to contribute code to OkHttp you can do so through GitHub by
forking the repository and sending a pull request.

When submitting code, please make every effort to follow existing conventions
and style in order to keep the code as readable as possible. Please also make
sure your code compiles by running `./gradlew check`. Checkstyle failures
during compilation indicate errors in your style and can be viewed in the
`checkstyle-result.xml` file.

Some general advice

- Don’t change public API lightly, avoid if possible, and include your reasoning in the PR if essential.  It causes pain for developers who use OkHttp and sometimes runtime errors.
- Favour a working external library if appropriate.  There are many examples of OkHttp libraries that can sit on top or hook in via existing APIs.
- Get working code on a personal branch with tests before you submit a PR.
- OkHttp is a small and light dependency.  Don't introduce new dependencies or major new functionality.
- OkHttp targets the intersection of RFC correct *and* widely implemented.  Incorrect implementations that are very widely implemented e.g. a bug in Apache, Nginx, Google, Firefox should also be handled.

Before your code can be accepted into the project you must also sign the
[Individual Contributor License Agreement (CLA)][1].


 [1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: A reproducible problem
title: ''
labels: bug
assignees: ''

---

Good bug reports include a failing test! Writing a test helps you to isolate and describe the problem, and it helps us to fix it fast. Bug reports without a failing test or reproduction steps are likely to be closed.

Here’s an example test to get you started.
https://gist.github.com/swankjesse/981fcae102f513eb13ed


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea
title: ''
labels: enhancement
assignees: ''

---

Start by telling us what problem you’re trying to solve. Often a solution already exists!

Don’t send pull requests to implement new features without first getting our support. Sometimes we leave features out on purpose to keep the project small.


================================================
FILE: .github/ISSUE_TEMPLATE/question.md
================================================
---
name: Question
about: Use Stack Overflow instead
title: "\U0001F649"
labels: ''
assignees: ''

---

🛑 𝙎𝙏𝙊𝙋

This issue tracker is not the place for questions!

If you want to ask how to do something, or to understand why something isn't working the way you expect it to, use Stack Overflow. https://stackoverflow.com/questions/tagged/okhttp

We close all questions without reading them.


================================================
FILE: .github/renovate.json
================================================
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:recommended",
    "group:monorepos",
    "group:recommended",
    ":dependencyDashboard"
  ],
  "semanticCommits": "disabled",
  "labels": [
    "renovate"
  ],
  "ignoreDeps": [
    "com.squareup.okhttp3:okhttp",
    "com.squareup.okhttp3:okhttp-tls",
    "com.squareup.okhttp3:mockwebserver"
  ],
  "packageRules": [
    {
      "groupName": "bnd",
      "matchPackageNames": [
        "/biz.*/"
      ]
    },
    {
      "groupName": "graalvm",
      "matchPackageNames": [
        "/org.graalvm.*/"
      ]
    },
    {
      "matchPackageNames": [
        "org.objenesis:objenesis"
      ],
      "allowedVersions": "<=2.6"
    },
    {
      "extends": [
        "monorepo:jetty"
      ],
      "allowedVersions": "<10.0",
      "description": "JDK 11 requirement"
    },
    {
      "extends": [
        "monorepo:junit5"
      ],
      "allowedVersions": "<5.14.0",
    },
    {
      "matchPackageNames": [
        "org.junit-pioneer:junit-pioneer"
      ],
      "allowedVersions": "<2.0.0",
      "description": "JDK 11 requirement"
    },
    {
      "matchPackageNames": [
        "androidx.activity:activity-ktx"
      ],
      "allowedVersions": "<=1.11.0",
      "description": "Android minSdk 23 requirement"
    }
  ]
}


================================================
FILE: .github/workflows/build.yml
================================================
name: build

on:
  push:
    branches:
      - master
  pull_request:
    types: [opened, labeled, unlabeled, synchronize]

permissions:
  contents: read

env:
  GRADLE_OPTS: "-Xmx4g -Dorg.gradle.daemon=false -Dkotlin.incremental=false"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  publish:
    runs-on: ubuntu-latest
    if: github.repository == 'square/okhttp' && github.ref == 'refs/heads/master'

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: 21

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Upload Artifacts
        run: ./gradlew clean publish --stacktrace
        env:
          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_CENTRAL_USERNAME }}
          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }}
          ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SECRET_KEY }}
          ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_SECRET_PASSPHRASE }}

  validation:
    name: "Validation"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: gradle/actions/wrapper-validation@v5
      - name: Validate Renovate
        uses: rinchsan/renovate-config-validator@v0.2.0
        with:
          pattern: '.github/renovate.json'

  checks:
    permissions:
      checks: write # for mikepenz/action-junit-report
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: |
            11
            21

      - uses: graalvm/setup-graalvm@v1
        with:
          distribution: 'graalvm'
          java-version: 21
          github-token: ${{ secrets.GITHUB_TOKEN }}
          native-image-job-reports: true

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Run Checks
        run: ./gradlew check -PgraalBuild=true -x jvmTest -x test -x allTests -x java9Test

  jvm:
    permissions:
      checks: write # for mikepenz/action-junit-report
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        java-version:
          - 8
          - 11
          - 17
          - 21

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: |
            ${{ matrix.java-version }}
            21

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Run Tests
        run: ./gradlew test allTests -Ptest.java.version=${{ matrix.java-version }}

      - name: Publish Test Report
        if: github.repository == 'square/okhttp' && github.ref == 'refs/heads/master' && matrix.java-version == '11'
        uses: mikepenz/action-junit-report@v6
        with:
          report_paths: '**/build/test-results/*/TEST-*.xml'
          check_name: OpenJDK 11 Test Report

      - name: Publish Test Results
        uses: EnricoMi/publish-unit-test-result-action@v2
        if: github.repository == 'square/okhttp' && github.ref == 'refs/heads/master' && matrix.java-version == '11'
        with:
          files: |
            **/build/test-results/*/TEST-*.xml

  openjdk8alpn:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/master' || contains(github.event.pull_request.labels.*.name, 'jdkversions')

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Old JDK 8
        uses: actions/setup-java@v5
        with:
          distribution: 'zulu'
          java-version: 8.0.242

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: 21

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Run Tests
        run: ./gradlew test allTests -Ptest.java.version=8 -Pokhttp.platform=jdk8alpn -Palpn.boot.version=8.1.13.v20181017 -Dorg.gradle.java.installations.paths=/opt/hostedtoolcache/Java_Adopt_jdk/8.0.242-8.1/x64

  providers:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/master' || contains(github.event.pull_request.labels.*.name, 'providers')
    strategy:
      matrix:
        include:
          - provider: openjsse
            java-version: 8
          - provider: bouncycastle
            java-version: 21
          - provider: corretto
            java-version: 21
          - provider: conscrypt
            java-version: 21

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: |
            ${{ matrix.java-version }}
            21

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Run Tests
        run: ./gradlew test allTests -Pokhttp.platform=${{ matrix.provider }} -Ptest.java.version=${{ matrix.java-version }}

  openjdklatest:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDKs
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: |
            11
            17
            24

      - name: Allow incompatible JVM versions
        run: |
          echo 'kotlin.jvm.target.validation.mode=ignore' >> ./gradle.properties

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Run Tests
        run: ./gradlew test allTests -Ptest.java.version=24

  openjdkearlyaccess:
    runs-on: ubuntu-latest
    if: false # https://youtrack.jetbrains.com/issue/KTOR-8489

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: |
            11
            17
            25-ea

      - name: Allow incompatible JVM versions
        run: |
          echo 'kotlin.jvm.target.validation.mode=ignore' >> ./gradle.properties

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Run Tests
        run: ./gradlew test allTests -Ptest.java.version=25

  testwindows:
    runs-on: windows-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: 21

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Run Tests
        run: ./gradlew test allTests

  graal:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: 21

      - uses: graalvm/setup-graalvm@v1
        with:
          distribution: 'graalvm'
          java-version: 24
          github-token: ${{ secrets.GITHUB_TOKEN }}
          native-image-job-reports: true

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Build okcurl
        run: ./gradlew okcurl:nativeBuild

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Run native-image tests
        run: ./gradlew -PgraalBuild=true native-image-tests:nativeTest

  android:
    runs-on: ubuntu-latest
    timeout-minutes: 30

    strategy:
      fail-fast: false
      matrix:
        api-level:
          - 21
          - 23
          - 29
          - 34

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: 21

      - name: Enable KVM group perms
        # https://github.blog/changelog/2023-02-23-hardware-accelerated-android-virtualization-on-actions-windows-and-linux-larger-hosted-runners/
        run: |
          echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
          sudo udevadm control --reload-rules
          sudo udevadm trigger --name-match=kvm

      - name: Verify KVM
        run: |
          sudo apt-get install -y cpu-checker
          kvm-ok || echo "KVM is not accelerated"
          kvm-ok || exit 1

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Gradle cache
        run: ./gradlew :android-test:test

      - name: AVD System Image Cache
        uses: actions/cache@v5
        id: avd-cache
        with:
          key: avd-${{ runner.os }}-${{ matrix.api-level }}-${{ matrix.api-level >= 30 && 'x86_64' || 'x86' }}
          path: |
            ~/.android/avd/*
            ~/.android/adb*
            # Added the actual system image path
            ${{ env.ANDROID_HOME }}/system-images/android-${{ matrix.api-level }}

      - name: Create AVD and generate snapshot for caching
        if: steps.avd-cache.outputs.cache-hit != 'true'
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: ${{ matrix.api-level }}
          force-avd-creation: false
          arch: ${{ matrix.api-level >= 30 && 'x86_64' || 'x86' }}
          # No window, no audio, and use swiftshader for headless environments
          emulator-options: >
            -no-window
            -gpu swiftshader_indirect
            -noaudio
            -no-boot-anim
            -camera-back none
            -memory 2048
          disable-animations: true
          script: echo "Generated AVD snapshot for caching."

      - name: Run Tests
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: ${{ matrix.api-level }}
          arch: ${{ matrix.api-level == '34' && 'x86_64' || 'x86' }}
          script: ./gradlew -PandroidBuild=true connectedCheck
        env:
          API_LEVEL: ${{ matrix.api-level }}

      - name: Build Release App
        run: ./gradlew android-test-app:lint android-test-app:assembleRelease

  loom:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: |
            21
            24

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Run Tests
        run: ./gradlew test allTests -Pokhttp.platform=loom -Ptest.java.version=24 -PcontainerTests=true

  maven:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: 21

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Publish local snapshot
        run: ./gradlew publishToMavenLocal

      - name: Run maven test
        working-directory: ./maven-tests
        run: ./mvnw -q verify

  java9_modules:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: 24

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Test module-tests
        run: ./gradlew module-tests:test -PokhttpModuleTests=true

      - name: Run with Jlink
        run: ./gradlew module-tests:imageRun -PokhttpModuleTests=true



================================================
FILE: .github/workflows/containers.yml
================================================
name: containers

on:
  push:
    branches:
      - master
  pull_request:
    types: [opened, labeled, unlabeled, synchronize]

permissions:
  contents: read

env:
  GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false -Dkotlin.incremental=false"

jobs:
  test_containers:
    permissions:
      checks: write # for actions/upload-artifact
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/master' || contains(github.event.pull_request.labels.*.name, 'containers')

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: 21

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Run Container Tests
        run: ./gradlew container-tests:test -PcontainerTests=true


================================================
FILE: .github/workflows/docs.yml
================================================
name: docs

on:
  push:
    branches:
      - master
  pull_request:
    types: [opened, labeled, unlabeled, synchronize]

permissions:
  contents: read

env:
  GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false -Dkotlin.incremental=false"

jobs:
  test_docs:
    permissions:
      checks: write # for actions/upload-artifact
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/master' || contains(github.event.pull_request.labels.*.name, 'documentation')

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Configure JDK
        uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: 21

      - uses: actions/setup-python@v6
        with:
          python-version: 3.x

      - run: pip install mkdocs-material mkdocs-redirects

      - name: Generate Docs
        run: ./test_docs.sh

      - uses: actions/upload-artifact@v7
        with:
          name: docs
          path: site/


================================================
FILE: .github/workflows/publish.yml
================================================
name: publish

on:
  push:
    tags:
      - '**'

env:
  GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false -Dkotlin.incremental=false"

jobs:
  publish:
    runs-on: macos-15

    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version-file: .github/workflows/.java-version

      - run: ./gradlew publish
        env:
          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_CENTRAL_USERNAME }}
          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }}
          ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SECRET_KEY }}
          ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_SECRET_PASSPHRASE }}


================================================
FILE: .gitignore
================================================
.classpath
.kotlin
.project
.settings
.gradle
eclipsebin

bin
gen
build
out
lib
generated

target
pom.xml.*
release.properties
local.properties

.idea
*.iml
*.ipr
*.iws
*.log
classes

obj

.DS_Store

# Special Mkdocs files
docs/5.x
docs/changelog.md
docs/contributing.md
docs/index.md

# jenv
/.java-version
/site/
/docs/changelogs/changelog.md


================================================
FILE: .gitmodules
================================================
[submodule "okhttp-hpacktests/src/test/resources/hpack-test-case"]
	path = okhttp-hpacktests/src/test/resources/hpack-test-case
	url = https://github.com/http2jp/hpack-test-case.git


================================================
FILE: .junit.run/Not Slow.run.xml
================================================
<component name="ProjectRunConfigurationManager">
  <configuration default="false" name="Not Slow" type="JUnit" factoryName="JUnit" singleton="false">
    <useClassPathOnly />
    <option name="MAIN_CLASS_NAME" value="" />
    <option name="METHOD_NAME" value="" />
    <option name="TEST_OBJECT" value="tags" />
    <option name="VM_PARAMETERS" value="-ea -Djunit.jupiter.extensions.autodetection.enabled=true" />
    <option name="PARAMETERS" value="" />
    <option name="TEST_SEARCH_SCOPE">
      <value defaultName="wholeProject" />
    </option>
    <tag value="!Slow &amp; !Slowish &amp; !Remote &amp; !Android" />
    <method v="2">
      <option name="Make" enabled="true" />
    </method>
  </configuration>
</component>

================================================
FILE: .vscode/settings.json
================================================
{
    "java.configuration.updateBuildConfiguration": "interactive",
    "java.import.gradle.wrapper.enabled": true
}

================================================
FILE: BUG-BOUNTY.md
================================================
Serious about security
======================

Square recognizes the important contributions the security research community
can make. We therefore encourage reporting security issues with the code
contained in this repository.

If you believe you have discovered a security vulnerability, please follow the
guidelines at https://bugcrowd.com/engagements/blockopensource.


================================================
FILE: CHANGELOG.md
================================================
Change Log
==========

## Version 5.3.2

_2025-11-18_

 *  Fix: Don't delay triggering timeouts. In Okio 3.16.0 we introduced a regression that caused
    timeouts to fire later than they were supposed to.

 *  Upgrade: [Okio 3.16.4][okio_3_16_4].


## Version 5.3.1

_2025-11-16_

This release is the same as 5.3.0. Okio 3.16.3 didn't have a necessary fix!

*  Upgrade: [Okio 3.16.3][okio_3_16_3].


## Version 5.3.0

_2025-10-30_

 *  New: Add tags to `Call`, including computable tags. Use this to attach application-specific
    metadata to a `Call` in an `EventListener` or `Interceptor`. The tag can be read in any other
    `EventListener` or `Interceptor`.

    ```kotlin
      override fun intercept(chain: Interceptor.Chain): Response {
        chain.call().tag(MyAnalyticsTag::class) {
          MyAnalyticsTag(...)
        }

        return chain.proceed(chain.request())
      }
    ```

 *  New: Support request bodies on HTTP/1.1 connection upgrades.
 *  New: `EventListener.plus()` makes it easier to observe events in multiple listeners.
 *  Fix: Don't spam logs with _‘Method isLoggable in android.util.Log not mocked.’_ when using
    OkHttp in Robolectric and Paparazzi tests.
 *  Upgrade: [Kotlin 2.2.21][kotlin_2_2_21].
 *  Upgrade: [Okio 3.16.2][okio_3_16_2].
 *  Upgrade: [ZSTD-KMP 0.4.0][zstd_kmp_0_4_0]. This update fixes a bug that caused APKs to fail
    [16 KB ELF alignment checks][elf_alignment].


## Version 5.2.3

_2025-11-18_

 *  Fix: Don't delay triggering timeouts. In Okio 3.16.0 we introduced a regression that caused
    timeouts to fire later than they were supposed to.

 *  Upgrade: [Okio 3.16.4][okio_3_16_4].


## Version 5.2.2

_2025-11-16_

This release is the same as 5.2.1. Okio 3.16.3 didn't have a necessary fix!

 *  Upgrade: [Okio 3.16.3][okio_3_16_3].


## Version 5.2.1

_2025-10-09_

 *  Fix: Don't crash when calling `Socket.shutdownOutput()` or `shutdownInput()` on an `SSLSocket`
    on Android API 21 through 23. This method throws an `UnsupportedOperationException`, so we now
    catch that and close the underlying stream instead.

 *  Upgrade: [Okio 3.16.1][okio_3_16_1].


## Version 5.2.0

_2025-10-07_

 *  New: Support [HTTP 101] responses with `Response.socket`. This mechanism is only supported on
    HTTP/1.1. We also reimplemented our websocket client to use this new mechanism.

 *  New: The `okhttp-zstd` module negotiates [Zstandard (zstd)][zstd] compression with servers that
    support it. It integrates a new (unstable) [ZSTD-KMP] library, also from Square. Enable it like
    this:

    ```kotlin
    val client = OkHttpClient.Builder()
      .addInterceptor(CompressionInterceptor(Zstd, Gzip))
      .build()
    ```

 *  New: Support the `QUERY` HTTP method. You will need to set the `Request.cacheUrlOverride`
    property to cache calls made with this method. The `RequestBody.sha256()` may be helpful here;
    use it to compose a cache URL from the query body.

 *  New: Publish events when calls must wait to execute. `EventListener.dispatcherQueueStart()`
    is invoked when a call starts waiting, and `dispatcherQueueEnd()` is invoked when it's done.

 *  New: `Request.toCurl()` returns a copy-pasteable [curl] command consistent with Chrome’s and
    Firefox’s ‘copy as cURL’ features.

 *  New: Support [JPMS]. We replaced our `Automatic-Module-Name` metadata with proper
    `module-info.java` files.

 *  Fix: Recover gracefully when worker threads are interrupted. When we introduced fast fallback in
    OkHttp 5.0, we started using background threads while connecting. Sadly that code didn't handle
    interruptions well. This is now fixed.

 *  Upgrade: [Kotlin 2.2.20][kotlin_2_2_20].
 *  Upgrade: [Okio 3.16.0][okio_3_16_0].


## Version 5.1.0

_2025-07-07_

 *  New: `Response.peekTrailers()`. When we changed `Response.trailers()` to block instead of
    throwing in 5.0.0, we inadvertently removed the ability for callers to peek the trailers
    (by catching the `IllegalStateException` if they weren't available). This new API restores that
    capability.

 *  Fix: Don't crash on `trailers()` if the response doesn't have a body. We broke [Retrofit] users
    who read the trailers on the `raw()` OkHttp response, after its body was decoded.


## Version 5.0.0

_2025-07-02_

This is our first stable release of OkHttp since 2023. Here's the highlights if you're upgrading
from OkHttp 4.x:

**OkHttp is now packaged as separate JVM and Android artifacts.** This allows us to offer
platform-specific features and optimizations. If your build system handles [Gradle module metadata],
this change should be automatic.

**MockWebServer has a new coordinate and package name.** We didn’t like that our old artifact
depends on JUnit 4 so the new one doesn’t. It also has a better API built on immutable values. (We
intend to continue publishing the old `okhttp3.mockwebserver` artifact so there’s no urgency to
migrate.)

| Coordinate                                       | Package Name          | Description                       |
|:-------------------------------------------------| :-------------------- | :-------------------------------- |
| com.squareup.okhttp3:mockwebserver3:5.0.0        | mockwebserver3        | Core module. No JUnit dependency! |
| com.squareup.okhttp3:mockwebserver3-junit4:5.0.0 | mockwebserver3.junit4 | Optional JUnit 4 integration.     |
| com.squareup.okhttp3:mockwebserver3-junit5:5.0.0 | mockwebserver3.junit5 | Optional JUnit 5 integration.     |
| com.squareup.okhttp3:mockwebserver:5.0.0         | okhttp3.mockwebserver | Obsolete. Depends on JUnit 4.     |

**OkHttp now supports Happy Eyeballs ([RFC 8305][rfc_8305]) for IPv4+IPv6 networks.** It attempts
both IPv6 and IPv4 connections concurrently, keeping whichever connects first.

**We’ve improved our Kotlin APIs.** You can skip the builder:

```kotlin
val request = Request(
  url = "https://cash.app/".toHttpUrl(),
)
```

**OkHttp now supports [GraalVM].**

Here’s what has changed since 5.0.0-alpha.17:

 *  Upgrade: [Okio 3.15.0][okio_3_15_0].
 *  Upgrade: [Kotlin 2.2.0][kotlin_2_2_0].
 *  Fix: Don't crash with a `NoSuchMethodError` when using OkHttp with the Sentry SDK.
 *  Fix: Retain the query data in the old `okhttp3.mockwebserver.RecordedRequest.path` property. We
    inadvertently changed this behavior when we introduced the `mockwebserver3` API.


## Version 5.0.0-alpha.17

_2025-06-29_

This release stabilizes many APIs for the imminent OkHttp 5.0.0 release.

 *  New: `TrailersSource`, a public API for HTTP trailers. Production callers shouldn't need this
    as the API to read response trailers is unchanged. Testers may use this new stable API to
    supply trailers for a `Response`.

 *  New: `Path.asRequestBody()` is now a non-experimental API.

 *  New: `FileDescriptor.toRequestBody()` is now a non-experimental API.

 *  New: Stop using experimental coroutines APIs in our `okhttp-coroutines` artifact.

 *  Breaking: Move `gzip` from `RequestBody` to `Request.Builder`. This new API handles both
    compressing the request body and also adding the corresponding `Content-Encoding` header. Note
    that this function is sensitive to when it is called: the response body must be supplied before
    it can be compressed.

 *  Breaking: Remove `AddressPolicy`, `AsyncDns`, and `ConnectionListener` from the public API. We
    intend to ship a public API for these features, but we don't want to hold OkHttp 5.0.0 until
    those APIs are stable.

 *  Fix: Change `MockWebServer.close()` to cancel ongoing calls that are blocked on a delay.

 *  Upgrade: [Okio 3.13.0][okio_3_13_0].

This release also stabilizes many APIs in the `mockwebserver3` artifact that's new in 5.0.

 *  Breaking: `RecordedRequest.body` is now nullable. Null is used when the request does not have a
    body.

 *  Breaking: `RecordedRequest.chunkSizes` is now nullable. Null is used when the request does not
    use chunked encoding. This is different from an empty list - that indicates the request is
    chunked but has no data.

 *  Breaking: Replace `SocketPolicy` with a new type, `SocketEffect`. It splits triggers (request
    start, response body, etc.) from effects (closing the socket, closing the stream, etc.).

 *  Breaking: Rename `RecordedRequest.sequenceNumber` to `exchangeIndex` and introduce
    `connectionIndex` on that type. These properties may be useful when testing features like
    connection reuse.

 *  Breaking: Replace our parameters-based JUnit 5 extension with a new annotation, `@StartStop`.
    Put this annotation on a `MockWebServer` property and the extension will start it before your
    test executes and stop it after it completes. No further configuration is required.

    ```kotlin
    @StartStop val server = MockWebServer()
    ```

 *  Breaking: Don't automatically start `MockWebServer` after calls to accessors like `port`. Now
    these accessors will throw an `IllegalStateException` if the service has not yet been started.

 *  Breaking: Rename `RecordedRequest.path` to `RecordedRequest.target`. (This property is
    _sometimes_ a path, but it can also be a path and query, or a full URL.)

 *  Breaking: Decompose the `RecordedRequest.requestLine` into three properties, `method`, `target`,
    and `version`. This better suits HTTP/2 where the request line had to be synthesized from
    component headers.

 *  Breaking: Change `RecordedRequest.body` from a mutable `Buffer` to an immutable `ByteString`.

 *  Breaking: Adopt Okio's new `Socket` interface for `MockResponse.socketHandler`.

Note that any _Breaking_ changes above impact only APIs introduced in earlier 5.0.0-alpha releasees.
We don't break binary compatibility with non-alpha APIs.


## Version 5.0.0-alpha.16

_2025-05-29_

 *  Fix: The previous release would crash when running on Robolectric. We didn't anticipate
    running our Android artifact on the JVM platform!


## Version 5.0.0-alpha.15

_2025-05-28_

**This release introduces separate JVM and Android artifacts.** Until now, we've distributed OkHttp
as a JVM library that _detects_ Android capabilities at runtime, but that doesn't offer
Android-specific APIs. With this release we're starting to publish OkHttp as an AAR for Android
users in addition to our existing JAR for JVM users.

This first Android-specific artifact adopts Android's `assets` mechanism to embed the public suffix
data. We will build more Android integration in future releases.

The okhttp-android artifact first introduced in `5.0.0-alpha.7` is no longer available:

 *  The `AndroidAsyncDns` class moved to the `okhttp` artifact.
 *  The `AndroidLogging` class is no longer necessary. `LoggingEventListener` and
    `HttpLoggingInterceptor` write to logcat by default.

The rest of this release is our highest-quality release yet. Though we continue to use the word
_alpha_ in the version name, the only unstable thing in it is some non-final APIs tagged
`@ExperimentalOkHttpApi`. You can safely use this release in production.

 *  Fix: Attempt to read the response even if sending the request failed. This makes it possible
    to handle response statuses like `HTTP/1.1 431 "Request Header Fields Too Large`.

 *  Fix: Handle multiple 1xx responses.

 *  Fix: Address a performance bug in our internal task runner. We had a race condition that could
    result in it OkHttp starting a thread for each queued task, even when a single thread could run
    all of them.

 *  Fix: Address a performance bug in `MultipartReader`. We were scanning the entire input stream
    for a delimiter when we only needed to scan enough to return a result.

 *  Fix: Don't double-compress the public suffix database. OkHttp is usually distributed in a
    compressed file (like a JAR or APK), so compressing its internal data was redundant.

 *  Fix: Call `ProxySelector.connectFailed()` when a connection's initial TCP handshake fails.

 *  Fix: Change the signature of `Dispatcher` to accept a nullable `ExecutorService`. Changing this
    parameter to be non-null was an unintended signature change in OkHttp 4.0.

 *  New: `EventListener.retryDecision()` is called each time a request fails with an `IOException`.
    It notifies your listener if OkHttp will retry.

 *  New: `EventListener.followUpDecision()` is called each time a response is received. It notifies
    your listener if OkHttp has decided to make a follow-up request. Some common follow-ups are
    authentication challenges and redirects.

 *  New: Handy constants for `Headers.EMPTY`, `RequestBody.EMPTY`, and `ResponseBody.EMPTY`.

 *  New: OkHttp now calls `StrictMode.noteSlowCall()` when initializing TLS on Android. Use
    `StrictMode` to detect if your `OkHttpClient` is being initialized on the main thread.

 *  Upgrade: [Okio 3.12.0][okio_3_12_0].

 *  Upgrade: [Kotlin 2.1.21][kotlin_2_1_21].

 *  Upgrade: [kotlinx.coroutines 1.10.2][coroutines_1_10_2]. This is used by the optional
    `okhttp-coroutines` artifact.

 *  Upgrade: [AndroidX Startup 1.2.0][startup_1_2_0]. The Android variant of the `okhttp` artifact
    now depends on this. This is a new dependency.

 *  Upgrade: [AndroidX Annotation 1.9.1][annotation_1_9_1]. As above, the Android variant of the
    `okhttp` artifact now depends on this. This is also a new dependency.


## Version 5.0.0-alpha.14

_2024-04-17_

 *  Breaking: Move coroutines extensions to okhttp3.coroutines. Previously this artifact shared the
    `okhttp3` package name with our core module, which is incompatible with the Java Platform Module
    System.

 *  Fix in okhttp-coroutines: Publish a valid artifact. The coroutines JAR file in 5.0.0-alpha.13
    was corrupt and should not be used.


## Version 5.0.0-alpha.13

_2024-04-16_

 *  Breaking: Tag unstable new APIs as `@ExperimentalOkHttpApi`. We intend to release OkHttp 5.0
    without stabilizing these new APIs first.

    Do not use these experimental APIs in modules that may be executed using a version of OkHttp
    different from the version that the module was compiled with. Do not use them in published
    libraries. Do not use them if you aren't willing to track changes to them.

 *  Breaking: Drop support for Kotlin Multiplatform.

    We planned to support multiplatform in OkHttp 5.0, but after building it, we weren't happy with
    the implementation trade-offs. We can't use our HTTP client engine on Kotlin/JS, and we weren't
    prepared to build a TLS API for Kotlin/Native.

    We'd prefer a multiplatform HTTP client API that's backed by OkHttp on Android and JVM, and
    other engines on other platforms. [Ktor] does this pretty well today!

 *  Breaking: Use `kotlin.time.Duration` in APIs like `OkHttpClient.Builder.callTimeout()`. This
    update also drops support for the `DurationUnit` functions introduced in earlier alpha releases
    of OkHttp 5.

 *  Breaking: Reorder the parameters in the Cache constructor that was introduced in 5.0.0-alpha.3.

 *  New: `Request.Builder.cacheUrlOverride()` customizes the cache key used for a request. This can
    be used to make canonical URLs for the cache that omit insignificant query parameters or other
    irrelevant data.

    This feature may be used with `POST` requests to cache their responses. In such cases the
    request body is not used to determine the cache key, so you must manually add cache-relevant
    data to the override URL. For example, you could add a `request-body-sha256` query parameter so
    requests with the same POST data get the same cache entry.

 *  New: `HttpLoggingInterceptor.redactQueryParams()` configures the query parameters to redact
    in logs. For best security, don't put sensitive information in query parameters.

 *  New: `ConnectionPool.setPolicy()` configures a minimum connection pool size for a target
    address. Use this to proactively open HTTP connections.

    Connections opened to fulfill this policy are subject to the connection pool's
    `keepAliveDuration` but do not count against the pool-wide `maxIdleConnections` limit.

    This feature increases the client's traffic and the load on the server. Talking to your server's
    operators before adopting it.

 *  New in okhttp-android: `HttpLoggingInterceptor.androidLogging()` and
    `LoggingEventListener.androidLogging()` write HTTP calls or events to Logcat.

 *  New: `OkHttpClient.webSocketCloseTimeout` configures how long a web socket connection will wait
    for a graceful shutdown before it performs an abrupt shutdown.

 *  Fix: Honor `RequestBody.isOneShot()` in `MultipartBody`

 *  Fix in `okhttp-coroutines`: Don't leak response bodies in `executeAsync()`. We had a bug where
    we didn't call `Response.close()` if the coroutine was canceled before its response was
    returned.

 *  Upgrade: [Okio 3.9.0][okio_3_9_0].

 *  Upgrade: [Kotlin 1.9.23][kotlin_1_9_23].

 *  Upgrade: [Unicode® IDNA 15.1.0][idna_15_1_0]


## Version 5.0.0-alpha.12

_2023-12-17_

We took too long to cut this release and there's a lot of changes in it. We've been busy.

Although this release is labeled _alpha_, the only unstable thing in it is our new APIs. This
release has many critical bug fixes and is safe to run in production. We're eager to stabilize our
new APIs so we can get out of alpha.

 *  New: Support Java 21's virtual threads (‘OpenJDK Project Loom’). We changed OkHttp's internals
    to use `Lock` and `Condition` instead of `synchronized` for best resource utilization.

 *  New: Switch our Internationalized Domain Name (IDN) implementation to [UTS #46 Nontransitional
    Processing][uts46]. With this fix, the `ß` code point no longer maps to `ss`. OkHttp now embeds
    its own IDN mapping table in the library.

 *  New: Prefer the client's configured precedence order for TLS cipher suites. (OkHttp used to
    prefer the JDK’s precedence order.) This change may cause your HTTP calls to negotiate a
    different cipher suite than before! OkHttp's defaults cipher suites are selected for good
    security and performance.

 *  New: `ConnectionListener` publishes events for connects, disconnects, and use of pooled
    connections.

 *  Fix: Immediately update the connection's flow control window instead of waiting for the
    receiving stream to process it.

    This change may increase OkHttp's memory use for applications that make many concurrent HTTP
    calls and that can receive data faster than they can process it. Previously, OkHttp limited
    HTTP/2 to 16 MiB of unacknowledged data per connection. With this fix there is a limit of 16 MiB
    of unacknowledged data per stream and no per-connection limit.

 *  Fix: Don't close a `Deflater` while we're still using it to compress a web socket message. We
    had a severe bug where web sockets were closed on the wrong thread, which caused
    `NullPointerException` crashes in `Deflater`.

 *  Fix: Don't crash after a web socket fails its connection upgrade. We incorrectly released
    the web socket's connections back to the pool before their resources were cleaned up.

 *  Fix: Don't infinite loop when a received web socket message has self-terminating compressed
    data.

 *  Fix: Don't fail the call when the response code is ‘HTTP 102 Processing’ or ‘HTTP 103 Early
    Hints’.

 *  Fix: Honor interceptors' changes to connect and read timeouts.

 *  Fix: Recover gracefully when a cached response is corrupted on disk.

 *  Fix: Don't leak file handles when a cache disk write fails.

 *  Fix: Don't hang when the public suffix database cannot be loaded. We had a bug where a failure
    reading the public suffix database would cause subsequent reads to hang when they should have
    crashed.

 *  Fix: Avoid `InetAddress.getCanonicalHostName()` in MockWebServer. This avoids problems if the
    host machine's IP address has additional DNS registrations.

 *  New: Create a JPMS-compatible artifact for `JavaNetCookieJar`. Previously, multiple OkHttp
    artifacts defined classes in the `okhttp3` package, but this is forbidden by the Java module
    system. We've fixed this with a new package (`okhttp3.java.net.cookiejar`) and a new artifact,
    `com.squareup.okhttp3:okhttp-java-net-cookiehandler`. (The original artifact now delegates to
    this new one.)

    ```kotlin
    implementation("com.squareup.okhttp3:okhttp-java-net-cookiehandler:5.0.0-alpha.12")
    ```

 *  New: `Cookie.sameSite` determines whether cookies should be sent on cross-site requests. This
    is used by servers to defend against Cross-Site Request Forgery (CSRF) attacks.

 *  New: Log the total time of the HTTP call in `HttpLoggingInterceptor`.

 *  New: `OkHttpClient.Builder` now has APIs that use `kotlin.time.Duration`.

 *  New: `mockwebserver3.SocketPolicy` is now a sealed interface. This is one of several
    backwards-incompatible API changes that may impact early adopters of this alpha API.

 *  New: `mockwebserver3.Stream` for duplex streams.

 *  New: `mockwebserver3.MockResponseBody` for streamed response bodies.

 *  New: `mockwebserver3.MockResponse` is now immutable, with a `Builder`.

 *  New: `mockwebserver3.RecordedRequest.handshakeServerNames` returns the SNI (Server Name
    Indication) attribute from the TLS handshake.

 *  Upgrade: [Kotlin 1.9.21][kotlin_1_9_21].

 *  Upgrade: [Okio 3.7.0][okio_3_7_0].


## Version 5.0.0-alpha.11

_2022-12-24_

 *  New: Enable fast fallback by default. It's our implementation of Happy Eyeballs,
    [RFC 8305][rfc_8305]. Disable with `OkHttpClient.Builder.fastFallback(false)`.
 *  Fix: Don't log response bodies for server-sent events.
 *  Fix: Skip early hints (status code 103) responses.
 *  Fix: Don't log sensitive headers in `Request.toString()`.
 *  Fix: Don't crash when the dispatcher's `ExecutorService` is shutdown with many
    calls still enqueued.
 *  Upgrade: [GraalVM 22][graalvm_22].
 *  Upgrade: [Kotlin 1.7.10][kotlin_1_7_10].


## Version 5.0.0-alpha.10

_2022-06-26_

 *  Fix: Configure the multiplatform artifact (`com.squareup.okhttp3:okhttp:3.x.x`) to depend on the
    JVM artifact (`com.squareup.okhttp3:okhttp-jvm:3.x.x`) for Maven builds. This should work-around
    an issue where Maven doesn't interpret Gradle metadata.
 *  Fix: Make another attempt at supporting Kotlin 1.5.31 at runtime. We were crashing on
    `DurationUnit` which was a typealias in 1.5.x.
 *  Upgrade: [Okio 3.2.0][okio_3_2_0].


## Version 5.0.0-alpha.9

_2022-06-16_

 *  New: Enforce label length limits in URLs. `HttpUrl` now rejects URLs whose domains aren't valid.
    This includes overly-long domain names (longer than 253 characters), overly-long labels (more
    than 63 characters between dots), and empty labels.
 *  New: Don't include the `Content-Length` header in multipart bodies. Servers must delimit
    OkHttp's request bodies using the boundary only. (This change makes OkHttp more consistent with
    browsers and other HTTP clients.)
 *  New: Drop the `tunnelProxy` argument in `MockWebServer.useHttps()`. This change only impacts
    the OkHttp 5.x API which uses the `mockwebserver3` package.
 *  Fix: Don't call `toDuration()` which isn't available in kotlin-stdlib 1.4.


## Version 5.0.0-alpha.8

_2022-06-08_

 *  Fix: Change how `H2_PRIOR_KNOWLEDGE` works with HTTP proxies. Previously OkHttp assumed the
    proxy itself was a prior knowledge HTTP/2 server. With this update, OkHttp attempts a `CONNECT`
    tunnel just as it would with HTTPS. For prior knowledge with proxies OkHttp's is now consistent
    with these curl arguments:

    ```
    curl \
      --http2-prior-knowledge \
      --proxy localhost:8888 \
      --proxytunnel \
      http://squareup.com/robots.txt
    ```

 *  Fix: Support executing OkHttp on kotlin-stdlib versions as old as 1.4. The library still builds
    on up-to-date Kotlin releases (1.6.21) but no longer needs that version as a runtime dependency.
    This should make it easier to use OkHttp in Gradle plugins.

 *  Fix: Don't start the clock on response timeouts until the request body is fully transmitted.
    This is only relevant for duplex request bodies, because they are written concurrently when
    reading the response body.

 *  New: `MockResponse.inTunnel()` is a new `mockwebserver3` API to configure responses that are
    served while creating a proxy tunnel. This obsoletes both the `tunnelProxy` argument on
    `MockWebServer` and the `UPGRADE_TO_SSL_AT_END` socket option. (Only APIs on `mockwebserver3`
    are changed; the old `okhttp3.mockwebserver` APIs remain as they always have been.


## Version 5.0.0-alpha.7

_2022-04-26_

**This release introduces new Kotlin-friendly APIs.** When we migrated OkHttp from Java to Kotlin in
OkHttp 4.0, we kept our Java-first APIs. With 5.0 we're continuing to support Java and adding
additional improvements for Kotlin users. In this alpha we're excited to skip-the-builder for
requests and remove a common source of non-null assertions (`!!`) on the response body.

The alpha releases in the 5.0.0 series have production-quality code and an unstable API. We expect
to make changes to the APIs introduced in 5.0.0-alpha.X. These releases are safe for production use
and 'alpha' strictly signals that we're still experimenting with some new APIs. If you're eager for
the fixes or features below, please upgrade.

 *  New: Named and default parameters constructor for `Request`:

    ```
    val request = Request(
      url = "https://cash.app/".toHttpUrl(),
    )
    ```

 *  New: `Response.body` is now non-null. This was generally the case in OkHttp 4.x, but the Kotlin
    type declaration was nullable to support rare cases like the body on `Response.cacheResponse`,
    `Response.networkResponse`, and `Response.priorResponse`. In such cases the body is now
    non-null, but attempts to read its content will fail.
 *  New: Kotlin-specific APIs for request tags. Kotlin language users can lookup tags with a type
    parameter only, like `request.tag<MyTagClass>()`.
 *  New: MockWebServer has improved support for HTTP/1xx responses. Once you've migrated to the new
    `mockwebserver3` package, there's a new field, `MockResponse.informationalResponses`.
 *  Fix: Don't interpret trailers as headers after an HTTP/100 response. This was a bug only when
    the HTTP response body itself is empty.
 *  Fix: Don't crash when a fast fallback call has both a deferred connection and a held connection.
 *  Fix: `OkHttpClient` no longer implements `Cloneable`. It never should have; the class is
    immutable. This is left over from OkHttp 2.x (!) when that class was mutable. We're using the
    5.x upgrade as an opportunity to remove very obsolete APIs.
 *  Fix: Recover gracefully when Android's `NativeCrypto` crashes with `"ssl == null"`. This occurs
    when OkHttp retrieves ALPN state on a closed connection.
 *  Upgrade: [Kotlin 1.6.21][kotlin_1_6_21].
 *  Upgrade: [Okio 3.1.0][okio_3_1_0].


## Version 5.0.0-alpha.6

_2022-03-14_

 *  Fix: Don't attempt to close pooled connections. We saw occasional fast fallback calls crash in
    the previous alpha due to an unexpected race.


## Version 5.0.0-alpha.5

_2022-02-21_

 *  Fix: Don't include [Assertk][assertk] in OkHttp's production dependencies. This regression was
    introduced in the 5.0.0-alpha.4 release.
 *  Fix: Don't ask `Dns` implementations to resolve strings that are already IP addresses.
 *  Fix: Change fast fallback to race TCP handshakes only. To avoid wasted work, OkHttp will not
    attempt multiple TLS handshakes for the same call concurrently.
 *  Fix: Don't crash loading the public suffix database in GraalVM native images. The function
    `HttpUrl.topPrivateDomain()` uses a resource file to identify private domains, but we didn't
    include this file on GraalVM.


## Version 5.0.0-alpha.4

_2022-02-01_

**This release introduces fast fallback to better support mixed IPv4+IPv6 networks.** Fast fallback
is what we're calling our implementation of Happy Eyeballs, [RFC 8305][rfc_8305]. With this
feature OkHttp will attempt both IPv6 and IPv4 connections concurrently, keeping whichever connects
first. Fast fallback gives IPv6 connections a 250 ms head start so IPv6 is preferred on networks
where it's available.

To opt-in, configure your `OkHttpClient.Builder`:


```
OkHttpClient client = new OkHttpClient.Builder()
    .fastFallback(true)
    .build();
```

 *  New: Change the build from Kotlin-JVM to Kotlin-multiplatform (which includes JVM). Both
    native and JavaScript platforms are unstable preview releases and subject to
    backwards-incompatible changes in forthcoming releases.
 *  Fix: Don't crash loading the public suffix database resource in obfuscated builds.
 *  Fix: Don't silently ignore calls to `EventSource.cancel()` made from
    `EventSourceListener.onOpen()`.
 *  Fix: Enforce the max intermediates constraint when using pinned certificates with Conscrypt.
    This impacts Conscrypt when the server's presented certificates form both a trusted-but-unpinned
    chain and an untrusted-but-pinned chain.
 *  Upgrade: [Kotlin 1.6.10][kotlin_1_6_10].


## Version 5.0.0-alpha.3

_2021-11-22_

 *  Fix: Change `Headers.toString()` to redact authorization and cookie headers.
 *  Fix: Don't do DNS to get the hostname for `RecordedRequest.requestUrl`. This was doing a DNS
    lookup for the local hostname, but we really just wanted the `Host` header.
 *  Fix: Don't crash with a `InaccessibleObjectException` when detecting the platform trust manager
    on Java 17+.
 *  Fix: Don't crash if a cookie's value is a lone double quote character.
 *  Fix: Don't crash when canceling an event source created by `EventSources.processResponse()`.
 *  New: `Cache` now has a public constructor that takes an [okio.FileSystem]. This should make it
    possible to implement decorators for cache encryption or compression.
 *  New: `Cookie.newBuilder()` to build upon an existing cookie.
 *  New: Use TLSv1.3 when running on JDK 8u261 or newer.
 *  New: `QueueDispatcher.clear()` may be used to reset a MockWebServer instance.
 *  New: `FileDescriptor.toRequestBody()` may be particularly useful for users of Android's Storage
    Access Framework.
 *  Upgrade: [Kotlin 1.5.31][kotlin_1_5_31].
 *  Upgrade: [Okio 3.0.0][okio_3_0_0].


## Version 5.0.0-alpha.2

_2021-01-30_

**In this release MockWebServer has a new Maven coordinate and package name.** A longstanding
problem with MockWebServer has been its API dependency on JUnit 4. We've reorganized things to
remove that dependency while preserving backwards compatibility.

| Maven Coordinate                                         | Package Name          | Description                       |
| :------------------------------------------------------- | :-------------------- | :-------------------------------- |
| com.squareup.okhttp3:mockwebserver3:5.0.0-alpha.2        | mockwebserver3        | Core module. No JUnit dependency! |
| com.squareup.okhttp3:mockwebserver3-junit4:5.0.0-alpha.2 | mockwebserver3.junit4 | Optional JUnit 4 integration.     |
| com.squareup.okhttp3:mockwebserver3-junit5:5.0.0-alpha.2 | mockwebserver3.junit5 | Optional JUnit 5 integration.     |
| com.squareup.okhttp3:mockwebserver:5.0.0-alpha.2         | okhttp3.mockwebserver | Obsolete. Depends on JUnit 4.     |

The new APIs use `mockwebserver3` in both the Maven coordinate and package name. This new API is
**not stable** and will likely change before the final 5.0.0 release.

If you have code that subclasses `okhttp3.mockwebserver.QueueDispatcher`, this update is not source
or binary compatible. Migrating to the new `mockwebserver3` package will fix this problem.

 *  New: DNS over HTTPS is now a stable feature of OkHttp. We introduced this as an experimental
    module in 2018. We are confident in its stable API and solid implementation.
 *  Fix: Work around a crash in Android 10 and 11 that may be triggered when two threads
    concurrently close an SSL socket. This would have appeared in crash logs as
    `NullPointerException: bio == null`.
 *  Fix: Use plus `+` instead of `%20` to encode space characters in `FormBody`. This was a
    longstanding bug in OkHttp. The fix makes OkHttp consistent with major web browsers.
 *  Fix: Don't crash if Conscrypt returns a null version.
 *  Fix: Include the public suffix data as a resource in GraalVM native images.
 *  Fix: Fail fast when the cache is corrupted.
 *  Fix: Fail fast when a private key cannot be encoded.
 *  Fix: Fail fast when attempting to verify a non-ASCII hostname.
 *  Upgrade: [GraalVM 21][graalvm_21].
 *  Upgrade: [Kotlin 1.4.20][kotlin_1_4_20].


## Version 5.0.0-alpha.1

_2021-01-30_

**This release adds initial support for [GraalVM][graalvm].**

GraalVM is an exciting new platform and we're eager to adopt it. The startup time improvements over
the JVM are particularly impressive. Try it with okcurl:

```
$ ./gradlew okcurl:nativeImage
$ ./okcurl/build/graal/okcurl https://cash.app/robots.txt
```

This is our first release that supports GraalVM. Our code on this platform is less mature than JVM
and Android! Please report any issues you encounter: we'll fix them urgently.

 *  Fix: Attempt to read the response body even if the server canceled the request. This will cause
    some calls to return nice error codes like `HTTP/1.1 429 Too Many Requests` instead of transport
    errors like `SocketException: Connection reset` and `StreamResetException: stream was reset:
    CANCEL`.
 *  New: Support OSGi metadata.
 *  Upgrade: [Okio 2.9.0][okio_2_9_0].

    ```kotlin
    implementation("com.squareup.okio:okio:2.9.0")
    ```

Note that this was originally released on 2020-10-06 as 4.10.0-RC1. The only change from that
release is the version name.

## Version 4.x

See [4.x Change log](https://square.github.io/okhttp/changelogs/changelog_4x/) for the legacy version changelogs.

[GraalVM]: https://www.graalvm.org/
[Gradle module metadata]: https://docs.gradle.org/current/userguide/publishing_gradle_module_metadata.html
[HTTP 101]: https://httpwg.org/specs/rfc9110.html#status.101
[JPMS]: https://openjdk.org/projects/jigsaw/spec/
[Ktor]: https://ktor.io/
[Retrofit]: https://square.github.io/retrofit/
[ZSTD-KMP]: https://github.com/square/zstd-kmp
[androidx_startup]: https://developer.android.com/jetpack/androidx/releases/startup
[annotation_1_9_1]: https://developer.android.com/jetpack/androidx/releases/annotation#annotation-1.9.1
[assertk]: https://github.com/willowtreeapps/assertk
[coroutines_1_10_2]: https://github.com/Kotlin/kotlinx.coroutines/releases/tag/1.10.2
[curl]: https://curl.se/
[elf_alignment]: https://developer.android.com/guide/practices/page-sizes
[graalvm]: https://www.graalvm.org/
[graalvm_21]: https://www.graalvm.org/release-notes/21_0/
[graalvm_22]: https://www.graalvm.org/release-notes/22_2/
[idna_15_1_0]: https://www.unicode.org/reports/tr46/#Modifications
[kotlin_1_4_20]: https://github.com/JetBrains/kotlin/releases/tag/v1.4.20
[kotlin_1_5_31]: https://github.com/JetBrains/kotlin/releases/tag/v1.5.31
[kotlin_1_6_10]: https://github.com/JetBrains/kotlin/releases/tag/v1.6.10
[kotlin_1_6_21]: https://github.com/JetBrains/kotlin/releases/tag/v1.6.21
[kotlin_1_7_10]: https://github.com/JetBrains/kotlin/releases/tag/v1.7.10
[kotlin_1_9_21]: https://github.com/JetBrains/kotlin/releases/tag/v1.9.21
[kotlin_1_9_23]: https://github.com/JetBrains/kotlin/releases/tag/v1.9.23
[kotlin_2_1_21]: https://github.com/JetBrains/kotlin/releases/tag/v2.1.21
[kotlin_2_2_0]: https://github.com/JetBrains/kotlin/releases/tag/v2.2.0
[kotlin_2_2_20]: https://github.com/JetBrains/kotlin/releases/tag/v2.2.20
[kotlin_2_2_21]: https://github.com/JetBrains/kotlin/releases/tag/v2.2.21
[loom]: https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html
[okio_2_9_0]: https://square.github.io/okio/changelog/#version-290
[okio_3_0_0]: https://square.github.io/okio/changelog/#version-300
[okio_3_12_0]: https://square.github.io/okio/changelog/#version-3120
[okio_3_13_0]: https://square.github.io/okio/changelog/#version-3130
[okio_3_15_0]: https://square.github.io/okio/changelog/#version-3150
[okio_3_16_0]: https://square.github.io/okio/changelog/#version-3160
[okio_3_16_1]: https://square.github.io/okio/changelog/#version-3161
[okio_3_16_2]: https://square.github.io/okio/changelog/#version-3162
[okio_3_16_3]: https://square.github.io/okio/changelog/#version-3163
[okio_3_16_4]: https://square.github.io/okio/changelog/#version-3164
[okio_3_1_0]: https://square.github.io/okio/changelog/#version-310
[okio_3_2_0]: https://square.github.io/okio/changelog/#version-320
[okio_3_7_0]: https://square.github.io/okio/changelog/#version-370
[okio_3_9_0]: https://square.github.io/okio/changelog/#version-390
[rfc_8305]: https://tools.ietf.org/html/rfc8305
[startup_1_2_0]: https://developer.android.com/jetpack/androidx/releases/startup#1.2.0
[uts46]: https://www.unicode.org/reports/tr46
[zstd]: https://github.com/facebook/zstd
[zstd_kmp_0_4_0]: https://github.com/square/zstd-kmp/blob/main/CHANGELOG.md#version-040


================================================
FILE: CONTRIBUTING.md
================================================
Contributing
============

Keeping the project small and stable limits our ability to accept new contributors. We are not
seeking new committers at this time, but some small contributions are welcome.

If you've found a security problem, please follow our [bug bounty][security] program.

If you've found a bug, please contribute a failing test case so we can study and fix it.

If you have a new feature idea, please build it in an external library. There are
[many libraries][works_with_okhttp] that sit on top or hook in via existing APIs. If you build
something that integrates with OkHttp, tell us so that we can link it!

Before code can be accepted all contributors must complete our
[Individual Contributor License Agreement (CLA)][cla].


Code Contributions
------------------

Get working code on a personal branch with tests passing before you submit a PR:

```
./gradlew clean check
```

Please make every effort to follow existing conventions and style in order to keep the code as
readable as possible.

Contribute code changes through GitHub by forking the repository and sending a pull request. We
squash all pull requests on merge.


Gradle Setup
------------

```
$ cat local.properties
sdk.dir=PATH_TO_ANDROID_HOME/sdk
org.gradle.caching=true
```

Running Android Tests
---------------------

$ ANDROID_SDK_ROOT=PATH_TO_ANDROID_HOME/sdk ./gradlew :android-test:connectedCheck -PandroidBuild=true

Committer's Guides
------------------

 * [Concurrency][concurrency]
 * [Debug Logging][debug_logging]
 * [Releasing][releasing]

 [cla]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1
 [concurrency]: https://square.github.io/okhttp/concurrency/
 [debug_logging]: https://square.github.io/okhttp/debug_logging/
 [releasing]: https://square.github.io/okhttp/releasing/
 [security]: https://square.github.io/okhttp/security/
 [works_with_okhttp]: https://square.github.io/okhttp/works_with_okhttp/
 [okhttp_build]: https://github.com/square/okhttp/blob/master/okhttp/build.gradle


================================================
FILE: LICENSE.txt
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   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.


================================================
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.3.0/jar).

```kotlin
implementation("com.squareup.okhttp3:okhttp:5.3.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.3.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>
  <!-- Remove after OkHttp 5.2.0 with updated BOM. -->
  <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.3.0/jar).

```kotlin
testImplementation("com.squareup.okhttp3:mockwebserver3:5.3.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://square.github.io/okhttp/changelog/
 [conscrypt]: https://github.com/google/conscrypt/
 [get_example]: https://raw.github.com/square/okhttp/master/samples/guide/src/main/java/okhttp3/guide/GetExample.java
 [kotlin]: https://kotlinlang.org/
 [okhttp3_pro]: https://raw.githubusercontent.com/square/okhttp/master/okhttp/src/main/resources/META-INF/proguard/okhttp3.pro
 [okhttp]: https://square.github.io/okhttp/
 [okhttp_312x]: https://github.com/square/okhttp/tree/okhttp_3.12.x
 [okio]: https://github.com/square/okio
 [post_example]: https://raw.github.com/square/okhttp/master/samples/guide/src/main/java/okhttp3/guide/PostExample.java
 [r8_proguard]: https://square.github.io/okhttp/features/r8_proguard/
 [recipes]: https://square.github.io/okhttp/recipes/
 [snap]: https://s01.oss.sonatype.org/content/repositories/snapshots/
 [tls_history]: https://square.github.io/okhttp/tls_configuration_history/


================================================
FILE: android-test/build.gradle.kts
================================================
import okhttp3.buildsupport.androidBuild

plugins {
  id("okhttp.base-conventions")
  id("com.android.library")
  id("de.mannodermaus.android-junit5")
}

android {
  compileSdk = 36

  namespace = "okhttp.android.test"

  defaultConfig {
    minSdk = 21

    // Make sure to use the AndroidJUnitRunner (or a sub-class) in order to hook in the JUnit 5 Test Builder
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    testInstrumentationRunnerArguments += mapOf(
      "runnerBuilder" to "de.mannodermaus.junit5.AndroidJUnit5Builder",
      "notPackage" to "org.bouncycastle",
      "configurationParameters" to "junit.jupiter.extensions.autodetection.enabled=true"
    )
  }

  if (androidBuild) {
    sourceSets["androidTest"].java.srcDirs(
      "../okhttp-brotli/src/test/java",
      "../okhttp-dnsoverhttps/src/test/java",
      "../okhttp-logging-interceptor/src/test/java",
      "../okhttp-sse/src/test/java"
    )
  }

  compileOptions {
    targetCompatibility(JavaVersion.VERSION_11)
    sourceCompatibility(JavaVersion.VERSION_11)
  }

  testOptions {
    targetSdk = 34
    unitTests.isIncludeAndroidResources = true
  }


  // issue merging due to conflict with httpclient and something else
  packagingOptions.resources.excludes += setOf(
    "META-INF/DEPENDENCIES",
    "META-INF/LICENSE.md",
    "META-INF/LICENSE-notice.md",
    "README.txt",
    "org/bouncycastle/LICENSE",
    "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
  )
}

dependencies {
  implementation(libs.kotlin.reflect)
  implementation(libs.playservices.safetynet)
  "friendsImplementation"(projects.okhttp)
  "friendsImplementation"(projects.okhttpDnsoverhttps)

  testImplementation(projects.okhttp)
  testImplementation(libs.junit)
  testImplementation(libs.junit.ktx)
  testImplementation(libs.assertk)
  testImplementation(projects.okhttpTls)
  "friendsTestImplementation"(projects.loggingInterceptor)
  testImplementation(libs.androidx.test.runner)
  testImplementation(libs.robolectric)
  testImplementation(libs.androidx.espresso.core)
  testImplementation(libs.square.okio.fakefilesystem)
  testImplementation(projects.okhttpTestingSupport)
  testImplementation(libs.conscrypt.openjdk)
  testImplementation(libs.junit.jupiter.engine)
  testImplementation(libs.junit.vintage.engine)

  androidTestImplementation(projects.okhttpTestingSupport) {
    exclude("org.openjsse", "openjsse")
    exclude("org.conscrypt", "conscrypt-openjdk-uber")
    exclude("software.amazon.cryptools", "AmazonCorrettoCryptoProvider")
  }
  androidTestImplementation(libs.assertk)
  androidTestImplementation(libs.bouncycastle.bcprov)
  androidTestImplementation(libs.bouncycastle.bctls)
  androidTestImplementation(libs.conscrypt.android)
  androidTestImplementation(projects.mockwebserver3Junit4)
  androidTestImplementation(projects.mockwebserver3Junit5)
  androidTestImplementation(projects.okhttpBrotli)
  androidTestImplementation(projects.okhttpZstd)
  androidTestImplementation(projects.okhttpDnsoverhttps)
  androidTestImplementation(projects.loggingInterceptor)
  androidTestImplementation(projects.okhttpSse)
  androidTestImplementation(projects.okhttpTls)
  androidTestImplementation(libs.androidx.junit)
  androidTestImplementation(libs.androidx.espresso.core)
  androidTestImplementation(libs.http.client5)
  androidTestImplementation(libs.kotlin.test.common)
  androidTestImplementation(libs.kotlin.test.junit)
  androidTestImplementation(libs.square.moshi)
  androidTestImplementation(libs.square.moshi.kotlin)
  androidTestImplementation(libs.square.okio.fakefilesystem)

  androidTestImplementation(libs.androidx.test.runner)
  androidTestImplementation(libs.junit.jupiter.api)
  androidTestImplementation(libs.junit5android.core)
  androidTestRuntimeOnly(libs.junit5android.runner)
}

junitPlatform {
  filters {
    excludeTags("Remote")
  }
}


================================================
FILE: android-test/src/androidDeviceTest/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: android-test/src/androidDeviceTest/java/okhttp/android/test/OkHttpTest.kt
================================================
/*
 * Copyright (C) 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.
 */
package okhttp.android.test

import android.content.Context
import android.os.Build
import androidx.test.core.app.ApplicationProvider
import androidx.test.platform.app.InstrumentationRegistry
import com.google.android.gms.common.GooglePlayServicesNotAvailableException
import com.google.android.gms.security.ProviderInstaller
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import java.io.IOException
import java.net.InetAddress
import java.net.UnknownHostException
import java.security.KeyStore
import java.security.SecureRandom
import java.security.Security
import java.security.cert.Certificate
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import java.util.concurrent.atomic.AtomicInteger
import java.util.logging.Handler
import java.util.logging.Level
import java.util.logging.LogRecord
import java.util.logging.Logger
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLPeerUnverifiedException
import javax.net.ssl.SSLSocket
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
import mockwebserver3.MockResponse
import mockwebserver3.MockWebServer
import mockwebserver3.junit5.StartStop
import okhttp3.Cache
import okhttp3.Call
import okhttp3.CallEvent.CallEnd
import okhttp3.CallEvent.CallStart
import okhttp3.CallEvent.ConnectEnd
import okhttp3.CallEvent.ConnectStart
import okhttp3.CallEvent.ConnectionAcquired
import okhttp3.CallEvent.ConnectionReleased
import okhttp3.CallEvent.DnsEnd
import okhttp3.CallEvent.DnsStart
import okhttp3.CallEvent.FollowUpDecision
import okhttp3.CallEvent.ProxySelectEnd
import okhttp3.CallEvent.ProxySelectStart
import okhttp3.CallEvent.RequestHeadersEnd
import okhttp3.CallEvent.RequestHeadersStart
import okhttp3.CallEvent.ResponseBodyEnd
import okhttp3.CallEvent.ResponseBodyStart
import okhttp3.CallEvent.ResponseHeadersEnd
import okhttp3.CallEvent.ResponseHeadersStart
import okhttp3.CallEvent.SecureConnectEnd
import okhttp3.CallEvent.SecureConnectStart
import okhttp3.CertificatePinner
import okhttp3.CompressionInterceptor
import okhttp3.Connection
import okhttp3.DelegatingSSLSocket
import okhttp3.DelegatingSSLSocketFactory
import okhttp3.EventListener
import okhttp3.EventRecorder
import okhttp3.Gzip
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.OkHttpClientTestRule
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.TlsVersion
import okhttp3.brotli.Brotli
import okhttp3.dnsoverhttps.DnsOverHttps
import okhttp3.internal.concurrent.TaskRunner
import okhttp3.internal.http2.Http2
import okhttp3.internal.platform.Android10Platform
import okhttp3.internal.platform.AndroidPlatform
import okhttp3.internal.platform.Platform
import okhttp3.internal.platform.PlatformRegistry
import okhttp3.logging.LoggingEventListener
import okhttp3.testing.PlatformRule
import okhttp3.tls.HandshakeCertificates
import okhttp3.tls.internal.TlsUtil.localhost
import okhttp3.zstd.Zstd
import okio.ByteString.Companion.toByteString
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
import org.conscrypt.Conscrypt
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Assertions.fail
import org.junit.jupiter.api.Assumptions.assumeTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension
import org.opentest4j.TestAbortedException

@Tag("Slow")
class OkHttpTest {
  @Suppress("RedundantVisibilityModifier")
  @JvmField
  @RegisterExtension
  public val platform = PlatformRule()

  @Suppress("RedundantVisibilityModifier")
  @JvmField
  @RegisterExtension
  public val clientTestRule =
    OkHttpClientTestRule().apply {
      logger = Logger.getLogger(OkHttpTest::class.java.name)
    }

  private var client: OkHttpClient =
    clientTestRule
      .newClientBuilder()
      .addInterceptor(CompressionInterceptor(Zstd, Brotli, Gzip))
      .build()

  private val moshi =
    Moshi
      .Builder()
      .add(KotlinJsonAdapterFactory())
      .build()

  private val handshakeCertificates = localhost()

  @StartStop
  private val server = MockWebServer()

  @BeforeEach
  fun setup() {
    // Needed because of Platform.resetForTests
    PlatformRegistry.applicationContext = ApplicationProvider.getApplicationContext<Context>()
  }

  @Test
  fun testPlatform() {
    assertTrue(Platform.isAndroid)

    if (Build.VERSION.SDK_INT >= 29) {
      assertTrue(Platform.get() is Android10Platform)
    } else {
      assertTrue(Platform.get() is AndroidPlatform)
    }
  }

  @Test
  fun testRequest() {
    assumeNetwork()

    val request = Request.Builder().url("https://api.twitter.com/robots.txt").build()

    val response = client.newCall(request).execute()

    response.use {
      assertEquals(200, response.code)
    }
  }

  @Test
  fun testLocalhostInsecure() {
    assumeTrue(Build.VERSION.SDK_INT >= 24)

    val clientCertificates =
      HandshakeCertificates
        .Builder()
        .apply {
          if (Build.VERSION.SDK_INT >= 24) {
            addInsecureHost(server.hostName)
          }
        }.build()

    client =
      client
        .newBuilder()
        .sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager)
        .build()

    localhostInsecureRequest()
  }

  @Test
  fun testRequestWithSniRequirement() {
    assumeNetwork()

    val request = Request.Builder().url("https://docs.fabric.io/android/changelog.html").build()

    val response = client.newCall(request).execute()

    response.use {
      assertEquals(200, response.code)
    }
  }

  @Test
  fun testConscryptRequest() {
    assumeNetwork()

    try {
      Security.insertProviderAt(Conscrypt.newProviderBuilder().build(), 1)

      val request = Request.Builder().url("https://facebook.com/robots.txt").build()

      var socketClass: String? = null

      // Need fresh client to reset sslSocketFactoryOrNull
      client =
        OkHttpClient
          .Builder()
          .eventListenerFactory(
            clientTestRule.wrap(
              object : EventListener() {
                override fun connectionAcquired(
                  call: Call,
                  connection: Connection,
                ) {
                  socketClass = connection.socket().javaClass.name
                }
              },
            ),
          ).build()

      val response = client.newCall(request).execute()

      response.use {
        assertEquals(Protocol.HTTP_2, response.protocol)
        assertEquals(200, response.code)
        // see https://github.com/google/conscrypt/blob/b9463b2f74df42d85c73715a5f19e005dfb7b802/android/src/main/java/org/conscrypt/Platform.java#L613
        when {
          Build.VERSION.SDK_INT >= 24 -> {
            // Conscrypt 2.5+ defaults to SSLEngine-based SSLSocket
            assertEquals("org.conscrypt.Java8EngineSocket", socketClass)
          }

          Build.VERSION.SDK_INT < 22 -> {
            assertEquals("org.conscrypt.KitKatPlatformOpenSSLSocketImplAdapter", socketClass)
          }

          else -> {
            assertEquals("org.conscrypt.ConscryptFileDescriptorSocket", socketClass)
          }
        }
        assertEquals(TlsVersion.TLS_1_3, response.handshake?.tlsVersion)
      }
    } finally {
      Security.removeProvider("Conscrypt")
      client.close()
    }
  }

  @Test
  fun testConscryptRequestLocalhostInsecure() {
    try {
      Security.insertProviderAt(Conscrypt.newProviderBuilder().build(), 1)

      val clientCertificates =
        HandshakeCertificates
          .Builder()
          .addInsecureHost(server.hostName)
          .build()

      // Need fresh client to reset sslSocketFactoryOrNull
      client =
        OkHttpClient
          .Builder()
          .sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager)
          .build()

      localhostInsecureRequest()
    } finally {
      Security.removeProvider("Conscrypt")
      client.close()
    }
  }

  @Test
  fun testRequestUsesPlayProvider() {
    assumeNetwork()

    try {
      try {
        ProviderInstaller.installIfNeeded(InstrumentationRegistry.getInstrumentation().targetContext)
      } catch (gpsnae: GooglePlayServicesNotAvailableException) {
        throw TestAbortedException("Google Play Services not available", gpsnae)
      }

      val request = Request.Builder().url("https://facebook.com/robots.txt").build()

      var socketClass: String? = null

      // Need fresh client to reset sslSocketFactoryOrNull
      client =
        OkHttpClient
          .Builder()
          .eventListenerFactory(
            clientTestRule.wrap(
              object : EventListener() {
                override fun connectionAcquired(
                  call: Call,
                  connection: Connection,
                ) {
                  socketClass = connection.socket().javaClass.name
                }
              },
            ),
          ).build()

      val response = client.newCall(request).execute()

      response.use {
        assertEquals(Protocol.HTTP_2, response.protocol)
        assertEquals(200, response.code)
        assertEquals("com.google.android.gms.org.conscrypt.Java8FileDescriptorSocket", socketClass)
        assertEquals(TlsVersion.TLS_1_2, response.handshake?.tlsVersion)
      }
    } finally {
      Security.removeProvider("GmsCore_OpenSSL")
      client.close()
    }
  }

  @Test
  fun testRequestUsesPlayProviderLocalhostInsecure() {
    try {
      try {
        ProviderInstaller.installIfNeeded(InstrumentationRegistry.getInstrumentation().targetContext)
      } catch (gpsnae: GooglePlayServicesNotAvailableException) {
        throw TestAbortedException("Google Play Services not available", gpsnae)
      }

      val clientCertificates =
        HandshakeCertificates
          .Builder()
          .addPlatformTrustedCertificates()
          .addInsecureHost(server.hostName)
          .build()

      // Need fresh client to reset sslSocketFactoryOrNull
      client =
        OkHttpClient
          .Builder()
          .sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager)
          .build()

      localhostInsecureRequest()
    } finally {
      Security.removeProvider("GmsCore_OpenSSL")
      client.close()
    }
  }

  private fun localhostInsecureRequest() {
    server.useHttps(handshakeCertificates.sslSocketFactory())

    server.enqueue(MockResponse())

    val request = Request.Builder().url(server.url("/")).build()

    client.newCall(request).execute().use {
      assertEquals(200, it.code)
      assertEquals(listOf<Certificate>(), it.handshake?.peerCertificates)
    }
  }

  @Test
  fun testRequestUsesAndroidConscrypt() {
    assumeNetwork()

    val request = Request.Builder().url("https://facebook.com/robots.txt").build()

    var socketClass: String? = null

    client =
      client
        .newBuilder()
        .eventListenerFactory(
          clientTestRule.wrap(
            object : EventListener() {
              override fun connectionAcquired(
                call: Call,
                connection: Connection,
              ) {
                socketClass = connection.socket().javaClass.name
              }
            },
          ),
        ).build()

    val response = client.newCall(request).execute()

    response.use {
      assertEquals(Protocol.HTTP_2, response.protocol)
      if (Build.VERSION.SDK_INT >= 29) {
        assertEquals(TlsVersion.TLS_1_3, response.handshake?.tlsVersion)
      } else {
        assertEquals(TlsVersion.TLS_1_2, response.handshake?.tlsVersion)
      }
      assertEquals(200, response.code)
      assertTrue(socketClass?.startsWith("com.android.org.conscrypt.") == true)
    }
  }

  @Test
  fun testRequestUsesAndroidConscryptLocalhostInsecure() {
    assumeTrue(Build.VERSION.SDK_INT >= 24)

    val clientCertificates =
      HandshakeCertificates
        .Builder()
        .addPlatformTrustedCertificates()
        .apply {
          if (Build.VERSION.SDK_INT >= 24) {
            addInsecureHost(server.hostName)
          }
        }.build()

    client =
      client
        .newBuilder()
        .sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager)
        .build()

    localhostInsecureRequest()
  }

  @Test
  fun testHttpRequestNotBlockedOnLegacyAndroid() {
    assumeTrue(Build.VERSION.SDK_INT < 23)

    val request = Request.Builder().url("http://squareup.com/robots.txt").build()

    val response = client.newCall(request).execute()

    response.use {
      assertEquals(200, response.code)
    }
  }

  @Test
  @Disabled("cleartext required for additional okhttp wide tests")
  fun testHttpRequestBlocked() {
    assumeTrue(Build.VERSION.SDK_INT >= 23)

    val request = Request.Builder().url("http://squareup.com/robots.txt").build()

    try {
      client.newCall(request).execute()
      fail<Any>("expected cleartext blocking")
    } catch (_: java.net.UnknownServiceException) {
    }
  }

  data class HowsMySslResults(
    val unknown_cipher_suite_supported: Boolean,
    val beast_vuln: Boolean,
    val session_ticket_supported: Boolean,
    val tls_compression_supported: Boolean,
    val ephemeral_keys_supported: Boolean,
    val rating: String,
    val tls_version: String,
    val able_to_detect_n_minus_one_splitting: Boolean,
    val insecure_cipher_suites: Map<String, List<String>>,
    val given_cipher_suites: List<String>?,
  )

  @Test
  @Disabled
  fun testSSLFeatures() {
    assumeNetwork()

    val request = Request.Builder().url("https://www.howsmyssl.com/a/check").build()

    val response = client.newCall(request).execute()

    val results =
      response.use {
        moshi.adapter(HowsMySslResults::class.java).fromJson(response.body.string())!!
      }

    Platform.get().log("results $results", Platform.WARN)

    assertTrue(results.session_ticket_supported)
    assertEquals("Probably Okay", results.rating)
    // TODO map to expected versions automatically, test ignored for now.  Run manually.
    assertEquals("TLS 1.3", results.tls_version)
    assertEquals(0, results.insecure_cipher_suites.size)

    assertEquals(TlsVersion.TLS_1_3, response.handshake?.tlsVersion)
    assertEquals(Protocol.HTTP_2, response.protocol)
  }

  @Test
  fun testMockWebserverRequest() {
    enableTls()

    server.enqueue(MockResponse(body = "abc"))

    val request = Request.Builder().url(server.url("/")).build()

    val response = client.newCall(request).execute()

    response.use {
      assertEquals(200, response.code)
      assertEquals(Protocol.HTTP_2, response.protocol)
      val tlsVersion = response.handshake?.tlsVersion
      assertTrue(tlsVersion == TlsVersion.TLS_1_2 || tlsVersion == TlsVersion.TLS_1_3)
      assertEquals(
        "CN=localhost",
        (response.handshake!!.peerCertificates.first() as X509Certificate).subjectDN.name,
      )
    }
  }

  @Test
  fun testCertificatePinningFailure() {
    enableTls()

    val certificatePinner =
      CertificatePinner
        .Builder()
        .add(server.hostName, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
        .build()
    client = client.newBuilder().certificatePinner(certificatePinner).build()

    server.enqueue(MockResponse(body = "abc"))

    val request = Request.Builder().url(server.url("/")).build()

    try {
      client.newCall(request).execute()
      fail<Any>("")
    } catch (_: SSLPeerUnverifiedException) {
    }
  }

  @Test
  fun testCertificatePinningSuccess() {
    enableTls()

    val certificatePinner =
      CertificatePinner
        .Builder()
        .add(
          server.hostName,
          CertificatePinner.pin(handshakeCertificates.trustManager.acceptedIssuers[0]),
        ).build()
    client = client.newBuilder().certificatePinner(certificatePinner).build()

    server.enqueue(MockResponse(body = "abc"))

    val request = Request.Builder().url(server.url("/")).build()

    val response = client.newCall(request).execute()

    response.use {
      assertEquals(200, response.code)
    }
  }

  @Test
  fun testEventListener() {
    val eventRecorder = EventRecorder()

    enableTls()

    client =
      client
        .newBuilder()
        .eventListenerFactory(clientTestRule.wrap(eventRecorder))
        .build()

    server.enqueue(MockResponse(body = "abc1"))
    server.enqueue(MockResponse(body = "abc2"))

    val request = Request.Builder().url(server.url("/")).build()

    client.newCall(request).execute().use { response ->
      assertEquals(200, response.code)
    }

    assertEquals(
      listOf(
        CallStart::class,
        ProxySelectStart::class,
        ProxySelectEnd::class,
        DnsStart::class,
        DnsEnd::class,
        ConnectStart::class,
        SecureConnectStart::class,
        SecureConnectEnd::class,
        ConnectEnd::class,
        ConnectionAcquired::class,
        RequestHeadersStart::class,
        RequestHeadersEnd::class,
        ResponseHeadersStart::class,
        ResponseHeadersEnd::class,
        FollowUpDecision::class,
        ResponseBodyStart::class,
        ResponseBodyEnd::class,
        ConnectionReleased::class,
        CallEnd::class,
      ),
      eventRecorder.recordedEventTypes(),
    )

    eventRecorder.clearAllEvents()

    client.newCall(request).execute().use { response ->
      assertEquals(200, response.code)
    }

    assertEquals(
      listOf(
        CallStart::class,
        ConnectionAcquired::class,
        RequestHeadersStart::class,
        RequestHeadersEnd::class,
        ResponseHeadersStart::class,
        ResponseHeadersEnd::class,
        FollowUpDecision::class,
        ResponseBodyStart::class,
        ResponseBodyEnd::class,
        ConnectionReleased::class,
        CallEnd::class,
      ),
      eventRecorder.recordedEventTypes(),
    )
  }

  @Test
  fun testSessionReuse() {
    val sessionIds = mutableListOf<String>()

    enableTls()

    client =
      client
        .newBuilder()
        .eventListenerFactory(
          clientTestRule.wrap(
            object : EventListener() {
              override fun connectionAcquired(
                call: Call,
                connection: Connection,
              ) {
                val sslSocket = connection.socket() as SSLSocket

                sessionIds.add(
                  sslSocket.session.id
                    .toByteString()
                    .hex(),
                )
              }
            },
          ),
        ).build()

    server.enqueue(MockResponse(body = "abc1"))
    server.enqueue(MockResponse(body = "abc2"))

    val request = Request.Builder().url(server.url("/")).build()

    client.newCall(request).execute().use { response ->
      assertEquals(200, response.code)
    }

    client.connectionPool.evictAll()
    assertEquals(0, client.connectionPool.connectionCount())

    client.newCall(request).execute().use { response ->
      assertEquals(200, response.code)
    }

    assertEquals(2, sessionIds.size)
    assertEquals(sessionIds[0], sessionIds[1])
  }

  @Test
  fun testDnsOverHttps() {
    assumeNetwork()

    client =
      client
        .newBuilder()
        .eventListenerFactory(clientTestRule.wrap(LoggingEventListener.Factory()))
        .build()

    val dohDns = buildCloudflareIp(client)
    val dohEnabledClient =
      client
        .newBuilder()
        .eventListener(EventListener.NONE)
        .dns(dohDns)
        .build()

    dohEnabledClient.get("https://www.twitter.com/robots.txt")
    dohEnabledClient.get("https://www.facebook.com/robots.txt")
  }

  @Test
  fun testCustomTrustManager() {
    assumeNetwork()

    val trustManager =
      object : X509TrustManager {
        override fun checkClientTrusted(
          chain: Array<out X509Certificate>?,
          authType: String?,
        ) {}

        override fun checkServerTrusted(
          chain: Array<out X509Certificate>?,
          authType: String?,
        ) {}

        override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
      }

    val sslContext =
      Platform.get().newSSLContext().apply {
        init(null, arrayOf(trustManager), null)
      }
    val sslSocketFactory = sslContext.socketFactory

    val hostnameVerifier = HostnameVerifier { _, _ -> true }

    client =
      client
        .newBuilder()
        .sslSocketFactory(sslSocketFactory, trustManager)
        .hostnameVerifier(hostnameVerifier)
        .build()

    client.get("https://www.facebook.com/robots.txt")
  }

  @Test
  fun testCustomSSLSocketFactoryWithoutALPN() {
    enableTls()

    server.enqueue(MockResponse(body = "abc"))

    val sslSocketFactory = client.sslSocketFactory
    val trustManager = client.x509TrustManager!!

    val delegatingSocketFactory =
      object : DelegatingSSLSocketFactory(sslSocketFactory) {
        override fun configureSocket(sslSocket: SSLSocket): SSLSocket =
          object : DelegatingSSLSocket(sslSocket) {
            override fun getApplicationProtocol(): String = throw UnsupportedOperationException()
          }
      }

    client =
      client
        .newBuilder()
        .sslSocketFactory(delegatingSocketFactory, trustManager)
        .build()

    val request = Request.Builder().url(server.url("/").toString()).build()
    val response = client.newCall(request).execute()
    response.use {
      assertEquals(200, response.code)
      assertEquals(Protocol.HTTP_1_1, response.protocol)
    }
  }

  @Test
  fun testCustomTrustManagerWithAndroidCheck() {
    assumeNetwork()

    var withHostCalled = false
    var withoutHostCalled = false
    val trustManager =
      object : X509TrustManager {
        override fun checkClientTrusted(
          chain: Array<out X509Certificate>?,
          authType: String?,
        ) {}

        override fun checkServerTrusted(
          chain: Array<out X509Certificate>?,
          authType: String?,
        ) {
          withoutHostCalled = true
        }

        // called by Android via reflection in X509TrustManagerExtensions
        @Suppress("unused", "UNUSED_PARAMETER")
        fun checkServerTrusted(
          chain: Array<out X509Certificate>,
          authType: String,
          hostname: String,
        ): List<X509Certificate> {
          withHostCalled = true
          return chain.toList()
        }

        override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
      }

    val sslContext =
      Platform.get().newSSLContext().apply {
        init(null, arrayOf(trustManager), null)
      }
    val sslSocketFactory = sslContext.socketFactory

    val hostnameVerifier = HostnameVerifier { _, _ -> true }

    client =
      client
        .newBuilder()
        .sslSocketFactory(sslSocketFactory, trustManager)
        .hostnameVerifier(hostnameVerifier)
        .build()

    client.get("https://www.facebook.com/robots.txt")

    if (Build.VERSION.SDK_INT < 24) {
      assertFalse(withHostCalled)
      assertTrue(withoutHostCalled)
    } else {
      assertTrue(withHostCalled)
      assertFalse(withoutHostCalled)
    }
  }

  @Test
  fun testUnderscoreRequest() {
    assumeNetwork()

    val request =
      Request.Builder().url("https://example_underscore_123.s3.amazonaws.com/").build()

    try {
      client.newCall(request).execute().close()
      // Hopefully this passes
    } catch (ioe: IOException) {
      // https://github.com/square/okhttp/issues/5840
      when (ioe.cause) {
        is IllegalArgumentException -> {
          assertEquals("Android internal error", ioe.message)
        }

        is CertificateException -> {
          assertTrue(ioe.cause?.cause is IllegalArgumentException)
          assertEquals(
            true,
            ioe.cause
              ?.cause
              ?.message
              ?.startsWith("Invalid input to toASCII"),
          )
        }

        else -> {
          throw ioe
        }
      }
    }
  }

  @Test
  @Disabled("breaks conscrypt test")
  fun testBouncyCastleRequest() {
    assumeNetwork()

    try {
      Security.insertProviderAt(BouncyCastleProvider(), 1)
      Security.insertProviderAt(BouncyCastleJsseProvider(), 2)

      var socketClass: String? = null

      val trustManager =
        TrustManagerFactory
          .getInstance(TrustManagerFactory.getDefaultAlgorithm())
          .apply {
            init(null as KeyStore?)
          }.trustManagers
          .first() as X509TrustManager

      val sslContext =
        Platform.get().newSSLContext().apply {
          // TODO remove most of this code after https://github.com/bcgit/bc-java/issues/686
          init(null, arrayOf(trustManager), SecureRandom())
        }

      client =
        client
          .newBuilder()
          .sslSocketFactory(sslContext.socketFactory, trustManager)
          .eventListenerFactory(
            clientTestRule.wrap(
              object : EventListener() {
                override fun connectionAcquired(
                  call: Call,
                  connection: Connection,
                ) {
                  socketClass = connection.socket().javaClass.name
                }
              },
            ),
          ).build()

      val request = Request.Builder().url("https://facebook.com/robots.txt").build()

      val response = client.newCall(request).execute()

      response.use {
        assertEquals(Protocol.HTTP_2, response.protocol)
        assertEquals(200, response.code)
        assertEquals("org.bouncycastle.jsse.provider.ProvSSLSocketWrap", socketClass)
        assertEquals(TlsVersion.TLS_1_2, response.handshake?.tlsVersion)
      }
    } finally {
      Security.removeProvider("BCJSSE")
      Security.removeProvider("BC")
    }
  }

  @Test
  @Disabled("TODO: currently logging okhttp3.internal.concurrent.TaskRunner, okhttp3.internal.http2.Http2")
  fun testLoggingLevels() {
    enableTls()

    val testHandler =
      object : Handler() {
        val calls = mutableMapOf<String, AtomicInteger>()

        override fun publish(record: LogRecord) {
          calls
            .getOrPut(record.loggerName) { AtomicInteger(0) }
            .incrementAndGet()
        }

        override fun flush() {
        }

        override fun close() {
        }
      }.apply {
        level = Level.FINEST
      }

    Logger
      .getLogger("")
      .addHandler(testHandler)
    Logger
      .getLogger("okhttp3")
      .addHandler(testHandler)
    Logger
      .getLogger(Http2::class.java.name)
      .addHandler(testHandler)
    Logger
      .getLogger(TaskRunner::class.java.name)
      .addHandler(testHandler)
    Logger
      .getLogger(OkHttpClient::class.java.name)
      .addHandler(testHandler)

    server.enqueue(MockResponse(body = "abc"))

    val request =
      Request
        .Builder()
        .url(server.url("/"))
        .build()

    val response =
      client
        .newCall(request)
        .execute()

    response.use {
      assertEquals(200, response.code)
      assertEquals(Protocol.HTTP_2, response.protocol)
    }

    // Only logs to the test logger above
    // Will fail if "adb shell setprop log.tag.okhttp.Http2 DEBUG" is called
    assertEquals(setOf(OkHttpTest::class.java.name), testHandler.calls.keys)
  }

  fun testCachedRequest() {
    enableTls()

    server.enqueue(MockResponse(body = "abc", headers = Headers.headersOf("cache-control", "public, max-age=3")))
    server.enqueue(MockResponse(body = "abc"))

    val ctxt = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext

    val cacheSize = 1L * 1024 * 1024 // 1MB
    val cache = Cache(ctxt.cacheDir.resolve("testCache"), cacheSize)

    try {
      client =
        client
          .newBuilder()
          .cache(cache)
          .build()

      val request =
        Request
          .Builder()
          .url(server.url("/"))
          .build()

      client
        .newCall(request)
        .execute()
        .use {
          assertEquals(200, it.code)
          assertNull(it.cacheResponse)
          assertNotNull(it.networkResponse)

          assertEquals(3, it.cacheControl.maxAgeSeconds)
          assertTrue(it.cacheControl.isPublic)
        }

      client
        .newCall(request)
        .execute()
        .use {
          assertEquals(200, it.code)
          assertNotNull(it.cacheResponse)
          assertNull(it.networkResponse)
        }

      assertEquals(1, cache.hitCount())
      assertEquals(1, cache.networkCount())
      assertEquals(2, cache.requestCount())
    } finally {
      cache.delete()
    }
  }

  private fun OkHttpClient.get(url: String) {
    val request = Request.Builder().url(url).build()
    val response = this.newCall(request).execute()

    response.use {
      assertEquals(200, response.code)
    }
  }

  fun buildCloudflareIp(bootstrapClient: OkHttpClient): DnsOverHttps =
    DnsOverHttps
      .Builder()
      .client(bootstrapClient)
      .url("https://1.1.1.1/dns-query".toHttpUrl())
      .build()

  private fun enableTls() {
    client =
      client
        .newBuilder()
        .sslSocketFactory(
          handshakeCertificates.sslSocketFactory(),
          handshakeCertificates.trustManager,
        ).build()
    server.useHttps(handshakeCertificates.sslSocketFactory())
  }

  private fun assumeNetwork() {
    try {
      InetAddress.getByName("www.google.com")
    } catch (uhe: UnknownHostException) {
      throw TestAbortedException(uhe.message, uhe)
    }
  }

  fun OkHttpClient.close() {
    dispatcher.executorService.shutdown()
    connectionPool.evictAll()
  }
}


================================================
FILE: android-test/src/androidDeviceTest/java/okhttp/android/test/SingleAndroidTest.kt
================================================
/*
 * Copyright (C) 2025 Block, 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.
 */
package okhttp.android.test

import java.util.concurrent.TimeUnit
import kotlin.test.assertEquals
import mockwebserver3.MockResponse
import mockwebserver3.MockWebServer
import okhttp3.ConnectionPool
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.tls.internal.TlsUtil.localhost
import org.junit.jupiter.api.Test

/**
 * This single Junit 4 test is our Android test suite on API 21-25.
 */
class SingleAndroidTest {
  private val handshakeCertificates = localhost()

  private var client: OkHttpClient =
    OkHttpClient
      .Builder()
      .sslSocketFactory(
        handshakeCertificates.sslSocketFactory(),
        handshakeCertificates.trustManager,
      ).connectionPool(ConnectionPool(0, 1, TimeUnit.SECONDS))
      .build()

  private val server =
    MockWebServer()

  @Test
  fun testHttpsRequest() {
    server.useHttps(handshakeCertificates.sslSocketFactory())

    server.enqueue(MockResponse())
    server.start()

    val request = Request.Builder().url(server.url("/")).build()

    val response = client.newCall(request).execute()

    response.use {
      assertEquals(200, response.code)
    }

    while (client.connectionPool.connectionCount() > 0) {
      Thread.sleep(1000)
    }
  }

  @Test
  fun testHttpRequest() {
    server.enqueue(MockResponse())
    server.start()

    val request = Request.Builder().url(server.url("/")).build()

    val response = client.newCall(request).execute()

    response.use {
      assertEquals(200, response.code)
    }

    while (client.connectionPool.connectionCount() > 0) {
      Thread.sleep(1000)
    }
  }
}


================================================
FILE: android-test/src/androidDeviceTest/java/okhttp/android/test/StrictModeTest.kt
================================================
/*
 * Copyright (C) 2025 Block, 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.
 */
package okhttp.android.test

import android.os.StrictMode
import android.os.StrictMode.ThreadPolicy
import android.os.strictmode.Violation
import androidx.test.filters.SdkSuppress
import assertk.assertThat
import assertk.assertions.hasSize
import assertk.assertions.isEmpty
import assertk.assertions.isEqualTo
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.internal.platform.Platform
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.parallel.Isolated

@Isolated
@SdkSuppress(minSdkVersion = 28)
class StrictModeTest {
  private val violations = mutableListOf<Violation>()

  @AfterEach
  fun cleanup() {
    StrictMode.setThreadPolicy(
      ThreadPolicy
        .Builder()
        .permitAll()
        .build(),
    )
  }

  @Test
  fun testInit() {
    Platform.resetForTests()

    applyStrictMode()

    // Not currently safe
    // See https://github.com/square/okhttp/pull/8248
    OkHttpClient()

    assertThat(violations).hasSize(1)
    assertThat(violations[0].message).isEqualTo("newSSLContext")
  }

  @Test
  fun testNewCall() {
    Platform.resetForTests()

    val client = OkHttpClient()

    applyStrictMode()

    // Safe on main
    client.newCall(Request("https://google.com/robots.txt".toHttpUrl()))

    assertThat(violations).isEmpty()
  }

  private fun applyStrictMode() {
    StrictMode.setThreadPolicy(
      ThreadPolicy
        .Builder()
        .detectCustomSlowCalls()
        .penaltyListener({ it.run() }) {
          violations.add(it)
        }.build(),
    )
  }
}


================================================
FILE: android-test/src/androidDeviceTest/java/okhttp/android/test/alpn/AlpnOverrideTest.kt
================================================
/*
 * Copyright (C) 2020 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.
 */
package okhttp.android.test.alpn

import android.os.Build
import android.util.Log
import assertk.assertThat
import assertk.assertions.isEqualTo
import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
import okhttp3.Call
import okhttp3.Connection
import okhttp3.ConnectionSpec
import okhttp3.DelegatingSSLSocketFactory
import okhttp3.EventListener
import okhttp3.OkHttpClient
import okhttp3.Request
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test

/**
 * Tests for ALPN overriding on Android.
 */
@Tag("Remote")
class AlpnOverrideTest {
  class CustomSSLSocketFactory(
    delegate: SSLSocketFactory,
  ) : DelegatingSSLSocketFactory(delegate) {
    override fun configureSocket(sslSocket: SSLSocket): SSLSocket {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        val parameters = sslSocket.sslParameters
        Log.d("CustomSSLSocketFactory", "old applicationProtocols: $parameters.applicationProtocols")
        parameters.applicationProtocols = arrayOf("x-amzn-http-ca")
        sslSocket.sslParameters = parameters
      }

      return sslSocket
    }
  }

  var client = OkHttpClient()

  @Test
  fun getWithCustomSocketFactory() {
    client =
      client
        .newBuilder()
        .sslSocketFactory(CustomSSLSocketFactory(client.sslSocketFactory), client.x509TrustManager!!)
        .connectionSpecs(
          listOf(
            ConnectionSpec
              .Builder(ConnectionSpec.MODERN_TLS)
              .supportsTlsExtensions(false)
              .build(),
          ),
        ).eventListener(
          object : EventListener() {
            override fun connectionAcquired(
              call: Call,
              connection: Connection,
            ) {
              val sslSocket = connection.socket() as SSLSocket
              println("Requested " + sslSocket.sslParameters.applicationProtocols.joinToString())
              println("Negotiated " + sslSocket.applicationProtocol)
            }
          },
        ).build()

    val request =
      Request
        .Builder()
        .url("https://www.google.com")
        .build()
    client.newCall(request).execute().use { response ->
      assertThat(response.code).isEqualTo(200)
    }
  }
}


================================================
FILE: android-test/src/androidDeviceTest/java/okhttp/android/test/letsencrypt/LetsEncryptClientTest.kt
================================================
/*
 * Copyright (C) 2020 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.
 */
package okhttp.android.test.letsencrypt

import android.os.Build
import assertk.assertThat
import assertk.assertions.isEqualTo
import java.security.cert.X509Certificate
import okhttp3.OkHttpClient
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.tls.HandshakeCertificates
import okhttp3.tls.decodeCertificatePem
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test

/**
 * Test for new Let's Encrypt Root Certificate.
 */
@Tag("Remote")
class LetsEncryptClientTest {
  @Test fun get() {
    // These tests wont actually run before Android 8.0 as per
    // https://github.com/mannodermaus/android-junit5
    // Raised https://github.com/mannodermaus/android-junit5/issues/228 to reevaluate
    val androidMorEarlier = Build.VERSION.SDK_INT <= 23

    val clientBuilder = OkHttpClient.Builder()

    if (androidMorEarlier) {
      val cert: X509Certificate =
        """
        -----BEGIN CERTIFICATE-----
        MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
        TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
        cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
        WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
        ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
        MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
        h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
        0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
        A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
        T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
        B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
        B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
        KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
        OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
        jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
        qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
        rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
        HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
        hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
        ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
        3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
        NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
        ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
        TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
        jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
        oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
        4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
        mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
        emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
        -----END CERTIFICATE-----
        """.trimIndent().decodeCertificatePem()

      val handshakeCertificates =
        HandshakeCertificates
          .Builder()
          // TODO reenable in official answers
//      .addPlatformTrustedCertificates()
          .addTrustedCertificate(cert)
          .build()

      clientBuilder
        .sslSocketFactory(
          handshakeCertificates.sslSocketFactory(),
          handshakeCertificates.trustManager,
        )
    }

    val client = clientBuilder.build()

    val request =
      Request
        .Builder()
        .url("https://valid-isrgrootx1.letsencrypt.org/robots.txt")
        .build()
    client.newCall(request).execute().use { response ->
      assertThat(response.code).isEqualTo(404)
      assertThat(response.protocol).isEqualTo(Protocol.HTTP_2)
    }
  }
}


================================================
FILE: android-test/src/androidDeviceTest/java/okhttp/android/test/sni/SniOverrideTest.kt
================================================
/*
 * Copyright (C) 2020 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.
 */
package okhttp.android.test.sni

import android.os.Build
import android.util.Log
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isEqualTo
import java.security.cert.X509Certificate
import javax.net.ssl.SNIHostName
import javax.net.ssl.SNIServerName
import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
import okhttp3.DelegatingSSLSocketFactory
import okhttp3.Dns
import okhttp3.OkHttpClient
import okhttp3.Protocol
import okhttp3.Request
import org.junit.jupiter.api.Assumptions.assumeTrue
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test

/**
 * Tests for SNI overriding on Android.
 */
@Tag("Remote")
class SniOverrideTest {
  var client =
    OkHttpClient
      .Builder()
      .build()

  @Test
  fun getWithCustomSocketFactory() {
    assumeTrue(Build.VERSION.SDK_INT >= 24)

    class CustomSSLSocketFactory(
      delegate: SSLSocketFactory,
    ) : DelegatingSSLSocketFactory(delegate) {
      override fun configureSocket(sslSocket: SSLSocket): SSLSocket {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
          val parameters = sslSocket.sslParameters
          val sni = parameters.serverNames
          Log.d("CustomSSLSocketFactory", "old SNI: $sni")
          parameters.serverNames = mutableListOf<SNIServerName>(SNIHostName("cloudflare-dns.com"))
          sslSocket.sslParameters = parameters
        }

        return sslSocket
      }
    }

    client =
      client
        .newBuilder()
        .sslSocketFactory(CustomSSLSocketFactory(client.sslSocketFactory), client.x509TrustManager!!)
        .hostnameVerifier { hostname, session ->
          val s = "hostname: $hostname peerHost:${session.peerHost}"
          Log.d("SniOverrideTest", s)
          try {
            val cert = session.peerCertificates[0] as X509Certificate
            for (name in cert.subjectAlternativeNames) {
              if (name[0] as Int == 2) {
                Log.d("SniOverrideTest", "cert: " + name[1])
              }
            }
            true
          } catch (e: Exception) {
            false
          }
        }.build()

    val request =
      Request
        .Builder()
        .url("https://sni.cloudflaressl.com/cdn-cgi/trace")
        .header("Host", "cloudflare-dns.com")
        .build()
    client.newCall(request).execute().use { response ->
      assertThat(response.code).isEqualTo(200)
      assertThat(response.protocol).isEqualTo(Protocol.HTTP_2)

      assertThat(response.body.string()).contains("h=cloudflare-dns.com")
    }
  }

  @Test
  fun getWithDns() {
    client =
      client
        .newBuilder()
        .dns {
          Dns.SYSTEM.lookup("sni.cloudflaressl.com")
        }.build()

    val request =
      Request
        .Builder()
        .url("https://cloudflare-dns.com/cdn-cgi/trace")
        .build()
    client.newCall(request).execute().use { response ->
      assertThat(response.code).isEqualTo(200)
      assertThat(response.protocol).isEqualTo(Protocol.HTTP_2)
      assertThat(response.body.string()).contains("h=cloudflare-dns.com")
    }
  }
}


================================================
FILE: android-test/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools" package="okhttp.android.test">

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

  <application android:usesCleartextTraffic="true" tools:targetApi="m"/>

</manifest>


================================================
FILE: android-test/src/main/res/values/strings.xml
================================================
<resources>
  <string name="app_name">android-test</string>
</resources>


================================================
FILE: android-test/src/main/res/xml/network_security_config.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <base-config cleartextTrafficPermitted="false">
  </base-config>
</network-security-config>

================================================
FILE: android-test/src/test/kotlin/okhttp/android/test/AndroidLoggingTest.kt
================================================
/*
 * Copyright (c) 2022 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.
 *
 */
package okhttp.android.test

import android.util.Log
import assertk.assertThat
import assertk.assertions.containsExactly
import assertk.assertions.containsOnly
import assertk.assertions.isNull
import java.net.UnknownHostException
import okhttp3.ConnectionSpec
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.internal.platform.AndroidPlatform
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.logging.LoggingEventListener
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.shadows.ShadowLog

@RunWith(RobolectricTestRunner::class)
class AndroidLoggingTest {
  val clientBuilder =
    OkHttpClient.Builder().connectionSpecs(listOf(ConnectionSpec.CLEARTEXT)).dns {
      throw UnknownHostException("shortcircuit")
    }

  val request = Request("http://google.com/robots.txt".toHttpUrl())

  @Test
  fun testHttpLoggingInterceptor() {
    val interceptor =
      HttpLoggingInterceptor().apply {
        level = HttpLoggingInterceptor.Level.BASIC
      }

    val client = clientBuilder.addInterceptor(interceptor).build()

    try {
      client.newCall(request).execute()
    } catch (uhe: UnknownHostException) {
      // expected
    }

    val logs = ShadowLog.getLogsForTag(AndroidPlatform.Tag)
    assertThat(logs.map { it.type }).containsOnly(Log.INFO)
    assertThat(
      logs.map {
        it.msg.replace(
          "\\d+".toRegex(),
          "",
        )
      },
    ).containsExactly(
      "--> GET http://google.com/robots.txt",
      "<-- HTTP FAILED: java.net.UnknownHostException: shortcircuit. ${request.url} (ms)",
    )
    // We should consider if these logs should retain Exceptions
    assertThat(logs.last().throwable).isNull()
  }

  @Test
  fun testLoggingEventListener() {
    val client = clientBuilder.eventListenerFactory(LoggingEventListener.Factory()).build()

    try {
      client.newCall(request).execute()
    } catch (uhe: UnknownHostException) {
      // expected
    }

    val logs = ShadowLog.getLogsForTag(AndroidPlatform.Tag)
    assertThat(logs.map { it.type }).containsOnly(Log.INFO)
    assertThat(
      logs.map {
        it.msg.replace(
          "\\[\\d+ ms] ".toRegex(),
          "",
        )
      },
    ).containsExactly(
      "callStart: Request{method=GET, url=http://google.com/robots.txt}",
      "proxySelectStart: http://google.com/",
      "proxySelectEnd: [DIRECT]",
      "dnsStart: google.com",
      "callFailed: java.net.UnknownHostException: shortcircuit",
    )
    // We should consider if these logs should retain Exceptions
    assertThat(logs.last().throwable).isNull()
  }
}


================================================
FILE: android-test/src/test/kotlin/okhttp/android/test/AndroidSocketAdapterTest.kt
================================================
/*
 * Copyright (C) 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.
 */
package okhttp.android.test

import java.security.Provider
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocket
import okhttp3.DelegatingSSLSocket
import okhttp3.DelegatingSSLSocketFactory
import okhttp3.Protocol.HTTP_1_1
import okhttp3.Protocol.HTTP_2
import okhttp3.internal.platform.android.AndroidSocketAdapter
import okhttp3.internal.platform.android.ConscryptSocketAdapter
import okhttp3.internal.platform.android.DeferredSocketAdapter
import okhttp3.internal.platform.android.SocketAdapter
import okhttp3.internal.platform.android.StandardAndroidSocketAdapter
import org.conscrypt.Conscrypt
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Assume.assumeFalse
import org.junit.Assume.assumeTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.ParameterizedRobolectricTestRunner
import org.robolectric.ParameterizedRobolectricTestRunner.Parameters

@RunWith(ParameterizedRobolectricTestRunner::class)
class AndroidSocketAdapterTest(
  val adapter: SocketAdapter,
) {
  val context: SSLContext by lazy {
    val provider: Provider = Conscrypt.newProviderBuilder().provideTrustManager(true).build()

    SSLContext.getInstance("TLS", provider).apply {
      init(null, null, null)
    }
  }

  @Test
  fun testMatchesSupportedSocket() {
    val socketFactory = context.socketFactory

    val sslSocket = socketFactory.createSocket() as SSLSocket
    assertTrue(adapter.matchesSocket(sslSocket))

    adapter.configureTlsExtensions(sslSocket, null, listOf(HTTP_2, HTTP_1_1))
    // not connected
    assertNull(adapter.getSelectedProtocol(sslSocket))
  }

  @Test
  fun testMatchesSupportedAndroidSocketFactory() {
    assumeTrue(adapter is StandardAndroidSocketAdapter)

    assertTrue(adapter.matchesSocketFactory(context.socketFactory))
    assertNotNull(adapter.trustManager(context.socketFactory))
  }

  @Test
  fun testDoesntMatchSupportedCustomSocketFactory() {
    assumeFalse(adapter is StandardAndroidSocketAdapter)

    assertFalse(adapter.matchesSocketFactory(context.socketFactory))
    assertNull(adapter.trustManager(context.socketFactory))
  }

  @Test
  fun testCustomSocket() {
    val socketFactory = DelegatingSSLSocketFactory(context.socketFactory)

    assertFalse(adapter.matchesSocketFactory(socketFactory))

    val sslSocket =
      object : DelegatingSSLSocket(context.socketFactory.createSocket() as SSLSocket) {}
    assertFalse(adapter.matchesSocket(sslSocket))

    adapter.configureTlsExtensions(sslSocket, null, listOf(HTTP_2, HTTP_1_1))
    // not connected
    assertNull(adapter.getSelectedProtocol(sslSocket))
  }

  companion object {
    @JvmStatic
    @Parameters(name = "{0}")
    fun data(): Collection<SocketAdapter> =
      listOfNotNull(
        DeferredSocketAdapter(ConscryptSocketAdapter.factory),
        DeferredSocketAdapter(AndroidSocketAdapter.factory("org.conscrypt")),
        StandardAndroidSocketAdapter.buildIfSupported("org.conscrypt"),
      )
  }
}


================================================
FILE: android-test/src/test/kotlin/okhttp/android/test/BaseOkHttpClientUnitTest.kt
================================================
/*
 * Copyright (c) 2025 Block, 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.
 *
 */
package okhttp.android.test

import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isNotNull
import assertk.assertions.isNull
import java.net.InetAddress
import java.net.UnknownHostException
import okhttp3.Cache
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okio.Path.Companion.toPath
import okio.fakefilesystem.FakeFileSystem
import org.junit.AssumptionViolatedException
import org.junit.Before
import org.junit.Test

abstract class BaseOkHttpClientUnitTest {
  private lateinit var client: OkHttpClient

  @Before
  fun setUp() {
    client =
      OkHttpClient
        .Builder()
        .cache(Cache(FakeFileSystem(), "/cache".toPath(), 10_000_000))
        .build()
  }

  @Test
  fun testRequestExternal() {
    assumeNetwork()

    val request = Request("https://www.google.com/robots.txt".toHttpUrl())

    val networkRequest =
      request
        .newBuilder()
        .build()

    val call = client.newCall(networkRequest)

    call.execute().use { response ->
      assertThat(response.code).isEqualTo(200)
      assertThat(response.cacheResponse).isNull()
    }

    val cachedCall = client.newCall(request)

    cachedCall.execute().use { response ->
      assertThat(response.code).isEqualTo(200)
      assertThat(response.cacheResponse).isNotNull()
    }
  }

  @Test
  open fun testPublicSuffixDb() {
    val httpUrl = "https://www.google.co.uk".toHttpUrl()
    assertThat(httpUrl.topPrivateDomain()).isEqualTo("google.co.uk")
  }

  private fun assumeNetwork() {
    try {
      InetAddress.getByName("www.google.com")
    } catch (uhe: UnknownHostException) {
      throw AssumptionViolatedException(uhe.message, uhe)
    }
  }
}


================================================
FILE: android-test/src/test/kotlin/okhttp/android/test/DisabledInitialiserTest.kt
================================================
/*
 * Copyright (c) 2025 Block, 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.
 *
 */
package okhttp.android.test

import assertk.all
import assertk.assertFailure
import assertk.assertions.cause
import assertk.assertions.hasClass
import assertk.assertions.hasMessage
import assertk.assertions.isNotNull
import java.io.IOException
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.internal.platform.Platform
import okhttp3.internal.platform.PlatformRegistry
import org.junit.AfterClass
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config

@RunWith(RobolectricTestRunner::class)
@Config(
  sdk = [23, 26, 30, 33, 35],
)
class DisabledInitialiserTest {
  @Before
  fun setContext() {
    // Ensure we aren't succeeding because of another test
    Platform.resetForTests()
    PlatformRegistry.applicationContext = null
  }

  @Test
  fun testWithoutContext() {
    val httpUrl = "https://www.google.co.uk".toHttpUrl()
    assertFailure { httpUrl.topPrivateDomain() }.all {
      hasMessage("Unable to load PublicSuffixDatabase.list resource.")
      cause().isNotNull().all {
        hasMessage(
          "Platform applicationContext not initialized. " +
            "Startup Initializer possibly disabled, " +
            "call OkHttp.initialize before test.",
        )
        hasClass<IOException>()
      }
    }
  }

  companion object {
    @AfterClass
    @JvmStatic
    fun resetContext() {
      // Ensure we don't make other tests fail
      Platform.resetForTests()
    }
  }
}


================================================
FILE: android-test/src/test/kotlin/okhttp/android/test/NonRobolectricOkHttpClientTest.kt
================================================
/*
 * Copyright (c) 2025 Block, 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.
 *
 */
package okhttp.android.test

import assertk.all
import assertk.assertFailure
import assertk.assertions.cause
import assertk.assertions.hasClass
import assertk.assertions.hasMessage
import assertk.assertions.isNotNull
import java.io.IOException
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

/**
 * Android test running with only stubs.
 */
@RunWith(JUnit4::class)
class NonRobolectricOkHttpClientTest : BaseOkHttpClientUnitTest() {
  @Test
  override fun testPublicSuffixDb() {
    assertFailure { super.testPublicSuffixDb() }.all {
      hasMessage("Unable to load PublicSuffixDatabase.list resource.")
      cause().isNotNull().all {
        hasMessage(
          "Platform applicationContext not initialized. " +
            "Possibly running Android unit test without Robolectric. " +
            "Android tests should run with Robolectric " +
            "and call OkHttp.initialize before test",
        )
        hasClass<IOException>()
      }
    }
  }
}


================================================
FILE: android-test/src/test/kotlin/okhttp/android/test/RobolectricOkHttpClientTest.kt
================================================
/*
 * Copyright (c) 2025 Block, 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.
 *
 */
package okhttp.android.test

import androidx.test.core.app.ApplicationProvider
import okhttp3.OkHttp
import org.junit.Before
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config

@RunWith(RobolectricTestRunner::class)
@Config(
  sdk = [23, 26, 30, 33, 35],
)
class RobolectricOkHttpClientTest : BaseOkHttpClientUnitTest() {
  @Before
  fun setContext() {
    // This is awkward because Robolectric won't run our initializers and we don't want test deps
    // https://github.com/robolectric/robolectric/issues/8461
    OkHttp.initialize(ApplicationProvider.getApplicationContext())
  }
}


================================================
FILE: android-test/src/test/kotlin/okhttp/android/test/ShadowDnsResolver.kt
================================================
/*
 * Copyright (C) 2024 Block, 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.
 */
package okhttp.android.test

import android.net.DnsResolver
import android.net.Network
import android.os.CancellationSignal
import java.net.InetAddress
import java.util.concurrent.Executor
import org.robolectric.annotation.Implementation
import org.robolectric.annotation.Implements
import org.robolectric.shadow.api.Shadow

@Implements(DnsResolver::class)
class ShadowDnsResolver {
  var responder: (Request) -> Unit = {
    it.callback.onAnswer(listOf(), 0)
  }

  data class Request(
    val network: Network?,
    val domain: String,
    val nsType: Int,
    val flags: Int,
    val callback: DnsResolver.Callback<List<InetAddress>>,
  )

  @Implementation
  fun query(
    network: Network?,
    domain: String,
    nsType: Int,
    flags: Int,
    executor: Executor,
    cancellationSignal: CancellationSignal?,
    callback: DnsResolver.Callback<List<InetAddress>>,
  ) {
    responder(Request(network, domain, nsType, flags, callback))
  }

  companion object {
    @Implementation
    @JvmStatic
    fun getInstance(): DnsResolver = Shadow.newInstance(DnsResolver::class.java, arrayOf(), arrayOf())
  }
}


================================================
FILE: android-test-app/build.gradle.kts
================================================
@file:Suppress("UnstableApiUsage")

import okhttp3.buildsupport.testJavaVersion


plugins {
  id("okhttp.base-conventions")
  id("com.android.application")
}

android {
  compileSdk = 36

  namespace = "okhttp.android.testapp"

  // Release APKs can't be tested currently with AGP
  testBuildType = "debug"

  defaultConfig {
    minSdk = 21
    targetSdk = 36
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }

  compileOptions {
    targetCompatibility(JavaVersion.VERSION_11)
    sourceCompatibility(JavaVersion.VERSION_11)
  }


  buildTypes {
    release {
      isShrinkResources = true
      isMinifyEnabled = true
      signingConfig = signingConfigs.getByName("debug")
      setProguardFiles(listOf(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"))
      testProguardFiles("test-proguard-rules.pro")
    }
  }

  lint {
    abortOnError = true
  }
}

dependencies {
  implementation(libs.playservices.safetynet)
  implementation(projects.okhttp)
  implementation(libs.androidx.activity)

  androidTestImplementation(libs.androidx.junit)
  androidTestImplementation(libs.androidx.espresso.core)
  androidTestImplementation(libs.androidx.test.runner)
  androidTestImplementation(libs.assertk)
}


================================================
FILE: android-test-app/proguard-rules.pro
================================================
# no rules should be needed

-whyareyoukeeping class okhttp3.internal.idn.IdnaMappingTable {
  *;
}


================================================
FILE: android-test-app/src/androidTest/kotlin/okhttp/android/testapp/IdnaTest.kt
================================================
/*
 * Copyright (c) 2025 Block, 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.
 */
package okhttp3.android

import okhttp3.HttpUrl.Companion.toHttpUrl
import org.junit.Assert.assertEquals
import org.junit.Test

class IdnaTest {
  @Test
  fun testHostnameFunction() {
    assertEquals("xn--n3h.net", "https://☃.net/robots.txt".toHttpUrl().host)
  }
}


================================================
FILE: android-test-app/src/androidTest/kotlin/okhttp/android/testapp/PublicSuffixDatabaseTest.kt
================================================
/*
 * Copyright (C) 2023 Block, 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.
 */
package okhttp3.android

import assertk.assertThat
import assertk.assertions.isEqualTo
import okhttp3.HttpUrl.Companion.toHttpUrl
import org.junit.Test

/**
 * Run with "./gradlew :android-test-app:connectedCheck -PandroidBuild=true" and make sure ANDROID_SDK_ROOT is set.
 */
class PublicSuffixDatabaseTest {
  @Test
  fun testTopLevelDomain() {
    assertThat("https://www.google.com/robots.txt".toHttpUrl().topPrivateDomain()).isEqualTo("google.com")
  }
}


================================================
FILE: android-test-app/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools" package="okhttp.android.testapp">

  <uses-permission android:name="android.permission.INTERNET" />

  <application
    android:allowBackup="true"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:name=".TestApplication"
  >
    <activity
      android:name=".MainActivity"
      android:exported="true">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>

    <activity
      android:name=".MainActivity2"
      android:process=":activity2"
      android:exported="true">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>

</manifest>


================================================
FILE: android-test-app/src/main/kotlin/okhttp/android/testapp/MainActivity.kt
================================================
/*
 * Copyright (C) 2023 Block, 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.
 */
package okhttp.android.testapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import okhttp3.Call
import okhttp3.Callback
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.internal.platform.AndroidPlatform
import okio.IOException

open class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val client = OkHttpClient()

    // Ensure we are compiling against the right variant
    println(AndroidPlatform.isSupported)

    val url = "https://github.com/square/okhttp".toHttpUrl()
    println(url.topPrivateDomain())

    client.newCall(Request(url)).enqueue(
      object : Callback {
        override fun onFailure(
          call: Call,
          e: IOException,
        ) {
          println("failed: $e")
        }

        override fun onResponse(
          call: Call,
          response: Response,
        ) {
          println("response: ${response.code}")
          response.close()
        }
      },
    )
  }
}


================================================
FILE: android-test-app/src/main/kotlin/okhttp/android/testapp/MainActivity2.kt
================================================
/*
 * Copyright (C) 2025 Block, 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.
 */
package okhttp.android.testapp

class MainActivity2 : MainActivity()


================================================
FILE: android-test-app/src/main/kotlin/okhttp/android/testapp/TestApplication.kt
================================================
/*
 * Copyright (C) 2023 Block, 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.
 */
package okhttp.android.testapp

import android.annotation.SuppressLint
import android.app.Application
import android.os.Build
import okhttp3.OkHttp

class TestApplication : Application() {
  override fun onCreate() {
    super.onCreate()

    if (isSecondaryProcess()) {
      OkHttp.initialize(applicationContext)
    }
  }

  private fun isSecondaryProcess(): Boolean = getProcess() != packageName

  @SuppressLint("DiscouragedPrivateApi")
  private fun getProcess(): String? =
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
      getProcessName()
    } else {
      Class
        .forName("android.app.ActivityThread")
        .getDeclaredMethod("currentProcessName")
        .apply { isAccessible = true }
        .invoke(null) as String
    }
}


================================================
FILE: android-test-app/src/main/res/values/strings.xml
================================================
<resources>
  <string name="app_name">android-test</string>
</resources>


================================================
FILE: android-test-app/src/main/res/xml/network_security_config.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <base-config cleartextTrafficPermitted="false">
  </base-config>
</network-security-config>


================================================
FILE: android-test-app/test-proguard-rules.pro
================================================
-dontwarn **


================================================
FILE: build-logic/build.gradle.kts
================================================
plugins {
  `kotlin-dsl`
  id("com.diffplug.spotless") version "8.4.0"
}

configure<com.diffplug.gradle.spotless.SpotlessExtension> {
  kotlin {
    target("src/**/*.kt")
    ktlint()
  }
  kotlinGradle {
    target("*.kts")
    targetExclude("build/**/*.kts")
    ktlint()
  }
}

repositories {
  google()
  mavenCentral()
  gradlePluginPortal()
}

dependencies {
  implementation(libs.gradlePlugin.kotlin)
  implementation(libs.gradlePlugin.mavenPublish)
  implementation(libs.gradlePlugin.dokka)
  implementation(libs.gradlePlugin.binaryCompatibilityValidator)
  implementation(libs.gradlePlugin.android)
  implementation(libs.gradlePlugin.bnd)
  implementation(libs.aqute.bnd)
  implementation(libs.gradlePlugin.animalsniffer)
  implementation(libs.gradlePlugin.spotless)
  implementation(libs.gradlePlugin.shadow)
  implementation(libs.gradlePlugin.graalvm)
  implementation(libs.gradlePlugin.ksp)
  implementation(libs.gradlePlugin.mrjar)
  implementation(libs.gradlePlugin.tapmoc)
  implementation(libs.androidx.lint.gradle)
  implementation(libs.kotlin.gradle.plugin.api)
}


================================================
FILE: build-logic/settings.gradle.kts
================================================
@file:Suppress("UnstableApiUsage")

pluginManagement {
  repositories {
    mavenCentral()
    gradlePluginPortal()
    google()
  }
}
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
rootProject.name = "build-logic"

dependencyResolutionManagement {
  repositories {
    mavenCentral()
    gradlePluginPortal()
    google()
  }
  versionCatalogs {
    create("libs") {
      from(files("../gradle/libs.versions.toml"))
    }
  }
}


================================================
FILE: build-logic/src/main/kotlin/AlpnVersions.kt
================================================
/*
 * Copyright (C) 2021 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
 *
 *    https://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.
 */

// https://www.eclipse.org/jetty/documentation/current/alpn-chapter.html#alpn-versions
private fun alpnBootVersionForPatchVersion(patchVersion: Int): String? =
  when (patchVersion) {
    in 0..24 -> "8.1.0.v20141016"
    in 25..30 -> "8.1.2.v20141202"
    in 31..50 -> "8.1.3.v20150130"
    in 51..59 -> "8.1.4.v20150727"
    in 60..64 -> "8.1.5.v20150921"
    in 65..70 -> "8.1.6.v20151105"
    in 71..77 -> "8.1.7.v20160121"
    in 78..101 -> "8.1.8.v20160420"
    in 102..111 -> "8.1.9.v20160720"
    in 112..120 -> "8.1.10.v20161026"
    in 121..160 -> "8.1.11.v20170118"
    in 161..181 -> "8.1.12.v20180117"
    in 191..242 -> "8.1.13.v20181017"
    else -> null
  }

/**
 * Returns the alpn-boot version specific to this OpenJDK 8 JVM, or null if this is not a Java 8 VM.
 * https://github.com/xjdr/xio/blob/master/alpn-boot.gradle
 */
fun alpnBootVersion(): String? {
  val version = System.getProperty("alpn.boot.version")

  if (version != null) {
    return version
  }

  val javaVersion = System.getProperty("java.version")
  val match = "1\\.8\\.0_(\\d+)(-.*)?".toRegex().find(javaVersion) ?: return null

  return alpnBootVersionForPatchVersion(match.groupValues.first().toInt())
}


================================================
FILE: build-logic/src/main/kotlin/BndBuildAction.kt
================================================
/*
 * Copyright (c) aQute SARL (2000, 2021). All Rights Reserved.
 *
 * 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.
 */

import aQute.bnd.gradle.BundleTaskExtension
import aQute.bnd.osgi.Builder
import aQute.bnd.osgi.Constants
import aQute.bnd.osgi.Jar
import aQute.bnd.osgi.Processor
import aQute.bnd.version.MavenVersion
import aQute.lib.io.IO
import aQute.lib.utf8properties.UTF8Properties
import java.io.File
import java.util.Properties
import java.util.jar.Manifest
import java.util.zip.ZipFile
import org.gradle.api.Action
import org.gradle.api.GradleException
import org.gradle.api.Task
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileCollection
import org.gradle.api.file.ProjectLayout
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.bundling.Jar as GradleJar
import org.gradle.api.tasks.bundling.ZipEntryCompression

/**
 * A static BuildAction that does not capture the Task instance, enabling Configuration Cache
 * compatibility.
 *
 * This class is based on bundled code from the BND Gradle Plugin.
 * https://github.com/bndtools/bnd/blob/master/gradle-plugins/biz.aQute.bnd.gradle/src/main/java/aQute/bnd/gradle/BundleTaskExtension.java
 */
class BndBuildAction(
  private val properties: MapProperty<String, Any>,
  private val classpath: ConfigurableFileCollection,
  private val sourcepath: FileCollection,
  private val bundleSymbolicName: Provider<String>,
  private val bundleVersion: Provider<String>,
  private val bndfile: RegularFileProperty,
  private val bnd: Provider<String>,
  private val layout: ProjectLayout,
  private val entryCompression: ZipEntryCompression,
  private val preserveFileTimestamps: Boolean,
) : Action<Task> {
  constructor(
    extension: BundleTaskExtension,
    task: GradleJar,
    sourceSet: FileCollection,
  ) : this(
    extension.properties,
    extension.classpath,
    // Sourcepath default: all source
    sourceSet,
    // Symbolic name default logic
    task.archiveBaseName.zip(task.archiveClassifier) { baseName, classifier ->
      if (classifier.isNullOrEmpty()) baseName else "$baseName-$classifier"
    },
    task.archiveVersion.orElse("0").map { version ->
      MavenVersion.parseMavenString(version).osGiVersion.toString()
    },
    extension.bndfile,
    extension.bnd,
    task.project.layout,
    task.entryCompression,
    task.isPreserveFileTimestamps,
  )

  override fun execute(task: Task) {
    task as GradleJar
    val temporaryDir = task.temporaryDir
    val projectDir = layout.projectDirectory.asFile

    val gradleProperties = Properties()
    properties.get().forEach { (k, v) ->
      if (v is Provider<*>) {
        val value = v.getOrNull()
        if (value != null) gradleProperties[k] = value
      } else {
        gradleProperties[k] = v
      }
    }

    // Set default values if not present
    if (!gradleProperties.containsKey(Constants.BUNDLE_SYMBOLICNAME)) {
      gradleProperties[Constants.BUNDLE_SYMBOLICNAME] = bundleSymbolicName.get()
    }
    if (!gradleProperties.containsKey(Constants.BUNDLE_VERSION)) {
      gradleProperties[Constants.BUNDLE_VERSION] = bundleVersion.get()
    }

    // Do not capture 'task' in gradleProperties to avoid serialization issues

    try {
      Builder(Processor(gradleProperties, false)).use { builder ->
        val temporaryBndFile = File.createTempFile("bnd", ".bnd", temporaryDir)
        IO.writer(temporaryBndFile).use { writer ->
          val bndFileVal = bndfile.asFile.getOrNull()
          if (bndFileVal != null && bndFileVal.isFile) {
            Processor(gradleProperties).let { p ->
              p.loadProperties(bndFileVal).store(writer, null)
            }
          } else {
            val bndVal = bnd.getOrElse("")
            if (bndVal.isNotEmpty()) {
              val props = UTF8Properties()
              props.load(bndVal, File(projectDir, "build.gradle.kts"), builder)
              props.replaceHere(projectDir).store(writer, null)
            }
          }
        }
        builder.setProperties(temporaryBndFile, projectDir)

        builder.setProperty("project.output", temporaryDir.canonicalPath)

        if (builder.`is`(Constants.NOBUNDLES)) return

        val archiveFile = task.archiveFile.get().asFile
        val archiveFileName = task.archiveFileName.get()

        val archiveCopyFile = File(temporaryDir, archiveFileName)
        IO.copy(archiveFile, archiveCopyFile)

        val bundleJar = Jar(archiveFileName, archiveCopyFile)

        if (builder.getProperty(Constants.REPRODUCIBLE) == null && !preserveFileTimestamps) {
          builder.setProperty(Constants.REPRODUCIBLE, "true")
        }
        if (builder.getProperty(Constants.COMPRESSION) == null) {
          builder.setProperty(
            Constants.COMPRESSION,
            when (entryCompression) {
              ZipEntryCompression.STORED -> Jar.Compression.STORE.name
              else -> Jar.Compression.DEFLATE.name
            },
          )
        }

        bundleJar.updateModified(archiveFile.lastModified(), "time of Jar task generated jar")
        bundleJar.manifest = Manifest()
        builder.setJar(bundleJar)

        val validClasspath = classpath.filter { it.exists() && (it.isDirectory || isZip(it)) }
        builder.setProperty("project.buildpath", validClasspath.asPath)
        builder.setClasspath(validClasspath.files.toTypedArray())

        val validSourcepath = sourcepath.filter { it.exists() }
        builder.setProperty("project.sourcepath", validSourcepath.asPath)
        builder.setSourcepath(validSourcepath.files.toTypedArray())

        val builtJar = builder.build()
        if (!builder.isOk) {
          builder.getErrors().forEach { task.logger.error("Error: $it") }
          builder.getWarnings().forEach { task.logger.warn("Warning: $it") }
          throw GradleException("Bundle $archiveFileName has errors")
        }

        builtJar.write(archiveFile)
        archiveFile.setLastModified(System.currentTimeMillis())
      }
    } catch (e: Exception) {
      throw GradleException("Bnd build failed", e)
    }
  }

  private fun isZip(file: File): Boolean =
    try {
      ZipFile(file).close()
      true
    } catch (e: Exception) {
      false
    }

  companion object {
    /**
     * BND is incompatible with Kotlin/Multiplatform because it assumes the JVM source set's name is
     * 'main'. Work around this by creating a 'main' source set that forwards to 'jvmMain'.
     */
    fun installWorkaround(project: org.gradle.api.Project): org.gradle.api.tasks.SourceSet {
      val sourceSets =
        project.extensions
          .getByType(org.gradle.api.plugins.JavaPluginExtension::class.java)
          .sourceSets
      val existingMain = sourceSets.findByName("main")
      if (existingMain != null) return existingMain

      val jvmMainSourceSet = sourceSets.getByName("jvmMain")
      val mainSourceSet =
        object : org.gradle.api.tasks.SourceSet by jvmMainSourceSet {
          override fun getName() = "main"

          override fun getProcessResourcesTaskName() = "${jvmMainSourceSet.processResourcesTaskName}ForFakeMain"

          override fun getCompileJavaTaskName() = "${jvmMainSourceSet.compileJavaTaskName}ForFakeMain"

          override fun getClassesTaskName() = "${jvmMainSourceSet.classesTaskName}ForFakeMain"

          override fun getCompileOnlyConfigurationName(): String = jvmMainSourceSet.compileOnlyConfigurationName + "ForFakeMain"

          override fun getCompileClasspathConfigurationName(): String = jvmMainSourceSet.compileClasspathConfigurationName + "ForFakeMain"

          override fun getImplementationConfigurationName(): String = jvmMainSourceSet.implementationConfigurationName + "ForFakeMain"

          override fun getAnnotationProcessorConfigurationName(): String =
            jvmMainSourceSet.annotationProcessorConfigurationName + "ForFakeMain"

          override fun getRuntimeClasspathConfigurationName(): String = jvmMainSourceSet.runtimeClasspathConfigurationName + "ForFakeMain"

          override fun getRuntimeOnlyConfigurationName(): String = jvmMainSourceSet.runtimeOnlyConfigurationName + "ForFakeMain"

          override fun getTaskName(
            verb: String?,
            target: String?,
          ) = "${jvmMainSourceSet.getTaskName(verb, target)}ForFakeMain"
        }
      sourceSets.add(mainSourceSet)
      project.tasks.named { it.endsWith("ForFakeMain") }.configureEach { onlyIf { false } }

      return mainSourceSet
    }
  }
}


================================================
FILE: build-logic/src/main/kotlin/JavaModules.kt
================================================
/*
 * Copyright (C) 2025 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
 *
 *    https://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.
 */

import me.champeau.mrjar.MultiReleaseExtension
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.jvm.toolchain.JavaToolchainService
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.named
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile

fun Project.applyJavaModules(
  moduleName: String,
  defaultVersion: Int = 8,
  javaModuleVersion: Int = 9,
  enableValidation: Boolean = true,
) {
  plugins.apply("me.champeau.mrjar")

  configure<MultiReleaseExtension> {
    targetVersions(defaultVersion, javaModuleVersion)
  }

  tasks.named<JavaCompile>("compileJava9Java").configure {
    val compileKotlinTask = tasks.getByName("compileKotlin") as KotlinJvmCompile
    dependsOn(compileKotlinTask)

    if (enableValidation) {
      compileKotlinTask.source(file("src/main/java9"))
    }

    // Ignore warnings about using 'requires transitive' on automatic modules.
    // not needed when compiling with recent JDKs, e.g. 17
    options.compilerArgs.add("-Xlint:-requires-transitive-automatic")

    // Patch the compileKotlinJvm output classes into the compilation so exporting packages works correctly.
    options.compilerArgs.addAll(
      listOf(
        "--patch-module",
        "$moduleName=${compileKotlinTask.destinationDirectory.get().asFile}",
      ),
    )

    classpath = compileKotlinTask.libraries
    modularity.inferModulePath.set(true)

    val javaToolchains = project.extensions.getByType<JavaToolchainService>()
    val javaPluginExtension = project.extensions.getByType<JavaPluginExtension>()
    javaCompiler.set(javaToolchains.compilerFor(javaPluginExtension.toolchain))
  }
}


================================================
FILE: build-logic/src/main/kotlin/Osgi.kt
================================================
/*
 * Copyright (C) 2021 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
 *
 *    https://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.
 */

import aQute.bnd.gradle.BundleTaskExtension
import org.gradle.api.Project
import org.gradle.api.artifacts.MinimalExternalModuleDependency
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.bundling.Jar as GradleJar
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.getByName
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.provideDelegate

fun Project.applyOsgi(vararg bndProperties: String) {
  plugins.withId("org.jetbrains.kotlin.jvm") { applyOsgi("jar", "osgiApi", bndProperties) }
}

private fun Project.applyOsgi(
  jarTaskName: String,
  osgiApiConfigurationName: String,
  bndProperties: Array<out String>,
) {
  val osgi = project.sourceSets.create("osgi")
  val osgiApi = project.configurations.getByName(osgiApiConfigurationName)

  project.dependencies { osgiApi(kotlinOsgi) }

  val jarTask = tasks.getByName<GradleJar>(jarTaskName)
  val bundleExtension =
    jarTask.extensions.create(
      BundleTaskExtension.NAME,
      BundleTaskExtension::class.java,
      jarTask,
    )
  bundleExtension.run {
    setClasspath(osgi.compileClasspath + sourceSets["main"].compileClasspath)
    properties.empty()
    bnd(*bndProperties)
  }
  jarTask.doLast(
    "buildBundle",
    BndBuildAction(bundleExtension, jarTask, sourceSets["main"].allSource),
  )
}

fun Project.applyOsgiMultiplatform(vararg bndProperties: String) {
  // BND is incompatible with Kotlin/Multiplatform because it assumes the JVM source set's
  // name is
  // 'main'. Work around this by creating a 'main' source set that forwards to 'jvmMain'.
  //
  // The forwarding SourceSet also needs to fake out some task names to prevent them from
  // being
  // registered twice.
  //
  // https://github.com/bndtools/bnd/issues/6590
  val mainSourceSet = BndBuildAction.installWorkaround(project)

  val osgiApi = configurations.create("osgiApi")
  dependencies { osgiApi(kotlinOsgi) }

  tasks.named<GradleJar>("jvmJar").configure {
    val bundleExtension =
      extensions.create(
        BundleTaskExtension.NAME,
        BundleTaskExtension::class.java,
        this,
      )
    val osgiApiArtifacts = osgiApi.artifacts
    val jvmMainClasses = tasks.named("jvmMainClasses").map { it.outputs.files }
    bundleExtension.apply {
      classpath(osgiApiArtifacts)
      classpath(jvmMainClasses)
      properties.empty()
      bnd(*bndProperties)
    }
    doLast("buildBundle", BndBuildAction(bundleExtension, this, mainSourceSet.allSource))
  }
}

val Project.sourceSets: SourceSetContainer
  get() = (this as ExtensionAware).extensions["sourceSets"] as SourceSetContainer

private val Project.kotlinOsgi: MinimalExternalModuleDependency
  get() =
    extensions
      .getByType(VersionCatalogsExtension::class.java)
      .named("libs")
      .findLibrary("kotlin.stdlib.osgi")
      .get()
      .get()


================================================
FILE: build-logic/src/main/kotlin/okhttp.base-conventions.gradle.kts
================================================
import org.gradle.api.artifacts.VersionCatalogsExtension
import okhttp3.buildsupport.platform
import okhttp3.buildsupport.testJavaVersion
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")

group = "com.squareup.okhttp3"
version = "5.4.0-SNAPSHOT"

val platform = project.platform
val testJavaVersion = project.testJavaVersion


// Friend configurations - moved here to be shared across all modules (including android-test)
val friendsApi = configurations.maybeCreate("friendsApi").apply {
  isCanBeResolved = true
  isCanBeConsumed = false
  isTransitive = true
}
val friendsImplementation = configurations.maybeCreate("friendsImplementation").apply {
  isCanBeResolved = true
  isCanBeConsumed = false
  isTransitive = false
}
val friendsTestImplementation = configurations.maybeCreate("friendsTestImplementation").apply {
  isCanBeResolved = true
  isCanBeConsumed = false
  isTransitive = false
}

configurations.configureEach {
  if (name == "implementation") {
    extendsFrom(friendsApi, friendsImplementation)
  }
  if (name == "api") {
    extendsFrom(friendsApi)
  }
  if (name == "testImplementation") {
    extendsFrom(friendsTestImplementation)
  }
}

tasks.withType<KotlinCompile>().configureEach {
  friendPaths.from(friendsApi.incoming.artifactView { }.files)
  friendPaths.from(friendsImplementation.incoming.artifactView { }.files)
  friendPaths.from(friendsTestImplementation.incoming.artifactView { }.files)
}

val resolvableConfigurations = configurations.filter { it.isCanBeResolved }
tasks.register("downloadDependencies") {
  description = "Download all dependencies to the Gradle cache"
  doLast {
    for (configuration in resolvableConfigurations) {
      configuration.files
    }
  }
}

normalization {
  runtimeClasspath {
    metaInf {
      ignoreAttribute("Bnd-LastModified")
    }
  }
}


================================================
FILE: build-logic/src/main/kotlin/okhttp.dokka-multimodule-conventions.gradle.kts
================================================
val okhttpDokka: String? by project
val dokkaBuild = okhttpDokka?.toBoolean() == true

if (dokkaBuild) {
  apply(plugin = "org.jetbrains.dokka")

  dependencies {
    add("dokka", project(":okhttp"))
    add("dokka", project(":okhttp-brotli"))
    add("dokka", project(":okhttp-coroutines"))
    add("dokka", project(":okhttp-dnsoverhttps"))
    add("dokka", project(":okhttp-java-net-cookiejar"))
    add("dokka", project(":logging-interceptor"))
    add("dokka", project(":okhttp-sse"))
    add("dokka", project(":okhttp-tls"))
    add("dokka", project(":okhttp-urlconnection"))
    add("dokka", project(":okhttp-zstd"))
    add("dokka", project(":mockwebserver"))
    add("dokka", project(":mockwebserver3"))
    add("dokka", project(":mockwebserver3-junit4"))
    add("dokka", project(":mockwebserver3-junit5"))
  }
}


================================================
FILE: build-logic/src/main/kotlin/okhttp.jvm-conventions.gradle.kts
================================================
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import tapmoc.TapmocExtension
import tapmoc.configureKotlinCompatibility

plugins {
  id("okhttp.base-conventions")
  id("com.gradleup.tapmoc")
}

val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")

fun library(alias: String) = libs.findLibrary(alias).get().get().let {
  "${it.module.group}:${it.module.name}:${it.versionConstraint.requiredVersion}"
}
fun version(alias: String) = libs.findVersion(alias).get().toString()

extensions.configure<JavaPluginExtension> {
  toolchain {
    languageVersion.set(JavaLanguageVersion.of(21))
  }
}

// Introduce in a separate change
//configureJavaCompatibility(javaVersion = 8)

configureKotlinCompatibility(version = version("kotlinCoreLibrariesVersion"))

tasks.withType<JavaCompile> {
  options.encoding = Charsets.UTF_8.toString()
  if (name.contains("Java9")) {
    sourceCompatibility = "9"
    targetCompatibility = "9"
  } else {
    sourceCompatibility = "1.8"
    targetCompatibility = "1.8"
  }
}

tasks.withType<KotlinCompile> {
  compilerOptions {
    jvmTarget.set(JvmTarget.JVM_1_8)
    freeCompilerArgs.addAll(
      "-Xjvm-default=all",
      "-Xexpect-actual-classes",
    )
  }
}

extensions.configure<TapmocExtension> {
  // Fail the build if any api dependency exposes incompatible Kotlin metadata, Kotlin stdlib, or Java bytecode version.
  checkDependencies()
}


================================================
FILE: build-logic/src/main/kotlin/okhttp.publish-conventions.gradle.kts
================================================
import com.vanniktech.maven.publish.JavadocJar
import com.vanniktech.maven.publish.KotlinJvm
import com.vanniktech.maven.publish.KotlinMultiplatform
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import kotlinx.validation.ApiValidationExtension
import kotlinx.validation.KotlinApiBuildTask
import kotlinx.validation.KotlinApiCompareTask

plugins {
  id("com.vanniktech.maven.publish.base")
  id("binary-compatibility-validator")
}

configure<MavenPublishBaseExtension> {
  publishToMavenCentral(automaticRelease = true)
  signAllPublications()
  pom {
    name.set(project.name)
    description.set("Square’s meticulous HTTP client for Java and Kotlin.")
    url.set("https://square.github.io/okhttp/")
    licenses {
      license {
        name.set("The Apache Software License, Version 2.0")
        url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
        distribution.set("repo")
      }
    }
    scm {
      connection.set("scm:git:https://github.com/square/okhttp.git")
      developerConnection.set("scm:git:ssh://git@github.com/square/okhttp.git")
      url.set("https://github.com/square/okhttp")
    }
    developers {
      developer {
        name.set("Square, Inc.")
      }
    }
  }

  if (project.name == "okhttp") {
    configure(KotlinMultiplatform(javadocJar = JavadocJar.Empty()))
  } else if (plugins.hasPlugin(JavaBasePlugin::class.java)) {
    configure(KotlinJvm(javadocJar = JavadocJar.Empty()))
  }
}

configure<ApiValidationExtension> {
  ignoredPackages += "okhttp3.logging.internal"
  ignoredPackages += "mockwebserver3.internal"
  ignoredPackages += "okhttp3.internal"
  ignoredPackages += "mockwebserver3.junit5.internal"
  ignoredPackages += "okhttp3.brotli.internal"
  ignoredPackages += "okhttp3.sse.internal"
  ignoredPackages += "okhttp3.tls.internal"
}

if (project.name == "okhttp") {
  // Workaround for https://github.com/Kotlin/binary-compatibility-validator/issues/312
  val apiBuild = tasks.register<KotlinApiBuildTask>("androidApiBuild") {
    outputApiFile = project.layout.buildDirectory.file("${this.name}/okhttp.api")
    inputClassesDirs.from(tasks.getByName("compileAndroidMain").outputs)
  }
  val apiCheck = tasks.register<KotlinApiCompareTask>("androidApiCheck") {
    group = "verification"
    projectApiFile = project.file("api/android/okhttp.api")
    generatedApiFile = apiBuild.flatMap(KotlinApiBuildTask::outputApiFile)
  }
  val apiDump = tasks.register<Copy>("androidApiDump") {
    from(apiBuild.flatMap(KotlinApiBuildTask::outputApiFile))
    destinationDir = project.file("api/android")
  }

  tasks.named("apiDump").configure { dependsOn(apiDump) }
  tasks.named("apiCheck").configure { dependsOn(apiCheck) }
}


================================================
FILE: build-logic/src/main/kotlin/okhttp.quality-conventions.gradle.kts
================================================
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import ru.vyarus.gradle.plugin.animalsniffer.AnimalSnifferExtension
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.withType
import ru.vyarus.gradle.plugin.animalsniffer.AnimalSniffer

plugins {
  id("okhttp.base-conventions")
  id("checkstyle")
  id("ru.vyarus.animalsniffer")
  id("com.android.lint")
  id("com.diffplug.spotless")
}

val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")

fun library(alias: String) = libs.findLibrary(alias).get().get().let {
  "${it.module.group}:${it.module.name}:${it.versionConstraint.requiredVersion}"
}
fun version(alias: String) = libs.findVersion(alias).get().toString()

tasks.withType<Checkstyle>().configureEach {
  exclude("**/CipherSuite.java")
}

val checkstyleConfig = configurations.maybeCreate("checkstyleConfig")
dependencies {
  add("checkstyleConfig", library("checkstyle")) {
    isTransitive = false
  }
}

configure<CheckstyleExtension> {
  config = resources.text.fromArchiveEntry(checkstyleConfig, "google_checks.xml")
  toolVersion = version("checkstyle")

  val sourceSets = project.extensions.findByType<SourceSetContainer>()
  val main = sourceSets?.findByName("main") ?: sourceSets?.findByName("jvmMain")
  if (main != null) {
    this.sourceSets = listOf(main)
  }
}

val androidSignature = configurations.maybeCreate("androidSignature")
val jvmSignature = configurations.maybeCreate("jvmSignature")

configure<AnimalSnifferExtension> {
  annotation = "okhttp3.internal.SuppressSignatureCheck"

  val sourceSets = project.extensions.findByType<SourceSetContainer>()
  val main = sourceSets?.findByName("main") ?: sourceSets?.findByName("jvmMain")
  if (main != null) {
    this.sourceSets = listOf(main)
  }

  signatures = androidSignature + jvmSignature
  failWithoutSignatures = false
}

// Default to only published modules
project.tasks.withType<AnimalSniffer> {
  val hasMavenPublish = project.extensions.findByType<MavenPublishBaseExtension>() != null
  onlyIf {
    hasMavenPublish
  }
}

dependencies {
  // Logic for signatures should be moved to the applying module or configured via extension
  // For now, we'll keep the standard ones and allow modules to add more
  androidSignature(library("signature-android-apilevel21")) { artifact { type = "signature" } }
  jvmSignature(library("codehaus-signature-java18")) { artifact { type = "signature" } }

  "lintChecks"(library("androidx-lint-gradle"))
}

configure<com.android.build.api.dsl.Lint> {
  xmlReport = true
  checkDependencies = true
}

configure<com.diffplug.gradle.spotless.SpotlessExtension> {
  kotlin {
    target("src/**/*.kt")
    targetExclude("**/kotlinTemplates/**/*.kt")
    ktlint()
    suppressLintsFor {
      step = "ktlint"
      shortCode = "standard:mixed-condition-operators"
    }
  }
  kotlinGradle {
    target("*.kts")
    ktlint()
  }
}


================================================
FILE: build-logic/src/main/kotlin/okhttp.testing-conventions.gradle.kts
================================================
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.artifacts.VersionCatalogsExtension
import okhttp3.buildsupport.platform
import okhttp3.buildsupport.testJavaVersion

plugins {
  id("okhttp.base-conventions")
}

val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")

fun library(alias: String) = libs.findLibrary(alias).get().get().let {
  "${it.module.group}:${it.module.name}:${it.versionConstraint.requiredVersion}"
}


val testRuntimeOnly = configurations.maybeCreate("testRuntimeOnly")
dependencies {
  testRuntimeOnly(library("junit-jupiter-engine"))
  testRuntimeOnly(library("junit-vintage-engine"))
  testRuntimeOnly(library("junit-platform-launcher"))
}

tasks.withType<Test> {
  useJUnitPlatform()
  jvmArgs("-Dokhttp.platform=$platform")

  if (platform == "loom") {
    jvmArgs("-Djdk.tracePinnedThreads=short")
  }
  if (platform == "openjsse") {
    if (testJavaVersion > 8) {
      throw GradleException("OpenJSSE is only supported on Java 8")
    }
  }

  val javaToolchains = project.extensions.getByType<JavaToolchainService>()
  javaLauncher.set(javaToolchains.launcherFor {
    languageVersion.set(JavaLanguageVersion.of(testJavaVersion))
  })

  maxParallelForks = Runtime.getRuntime().availableProcessors() * 2
  testLogging {
    exceptionFormat = TestExceptionFormat.FULL
  }

  systemProperty("okhttp.platform", platform)
  systemProperty("junit.jupiter.extensions.autodetection.enabled", "true")
}

tasks.withType<Test>().configureEach {
  environment("OKHTTP_ROOT", rootDir)
}

plugins.withId("org.jetbrains.kotlin.jvm") {
  val test = tasks.named("test")
  tasks.register("jvmTest") {
    description = "Get 'gradlew jvmTest' to run the tests of JVM-only modules"
    dependsOn(test)
  }
}


================================================
FILE: build-logic/src/main/kotlin/okhttp3/buildsupport/OkHttpBuildUtils.kt
================================================
/*
 * Copyright (c) 2026 OkHttp Authors
 *
 * 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.
 */
package okhttp3.buildsupport

import org.gradle.api.Project

val Project.platform: String
  get() = findProperty("okhttp.platform")?.toString() ?: "jdk9"

val Project.testJavaVersion: Int
  get() = findProperty("test.java.version")?.toString()?.toInt() ?: 21

val Project.androidBuild: Boolean
  get() = findProperty("androidBuild")?.toString()?.toBoolean() ?: false

val Project.alpnBootVersion: String?
  get() = findProperty("alpn.boot.version")?.toString()


================================================
FILE: build.gradle.kts
================================================
plugins {
  alias(libs.plugins.spotless) apply false
  alias(libs.plugins.android.library) apply false
  alias(libs.plugins.android.application) apply false
  alias(libs.plugins.kotlin.jvm) apply false
  alias(libs.plugins.kotlin.multiplatform) apply false
  alias(libs.plugins.kotlin.serialization) apply false
  alias(libs.plugins.dokka) apply false
  alias(libs.plugins.maven.publish) apply false
  alias(libs.plugins.binary.compatibility.validator) apply false
  alias(libs.plugins.animalsniffer) apply false
  alias(libs.plugins.android.junit5) apply false
  alias(libs.plugins.shadow) apply false
  alias(libs.plugins.graalvm) apply false
  alias(libs.plugins.ksp) apply false
  alias(
Download .txt
gitextract_j2sj9obc/

├── .devcontainer/
│   └── devcontainer.json
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── feature_request.md
│   │   └── question.md
│   ├── renovate.json
│   └── workflows/
│       ├── build.yml
│       ├── containers.yml
│       ├── docs.yml
│       └── publish.yml
├── .gitignore
├── .gitmodules
├── .junit.run/
│   └── Not Slow.run.xml
├── .vscode/
│   └── settings.json
├── BUG-BOUNTY.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── android-test/
│   ├── build.gradle.kts
│   └── src/
│       ├── androidDeviceTest/
│       │   ├── README.md
│       │   └── java/
│       │       └── okhttp/
│       │           └── android/
│       │               └── test/
│       │                   ├── OkHttpTest.kt
│       │                   ├── SingleAndroidTest.kt
│       │                   ├── StrictModeTest.kt
│       │                   ├── alpn/
│       │                   │   └── AlpnOverrideTest.kt
│       │                   ├── letsencrypt/
│       │                   │   └── LetsEncryptClientTest.kt
│       │                   └── sni/
│       │                       └── SniOverrideTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   └── res/
│       │       ├── values/
│       │       │   └── strings.xml
│       │       └── xml/
│       │           └── network_security_config.xml
│       └── test/
│           └── kotlin/
│               └── okhttp/
│                   └── android/
│                       └── test/
│                           ├── AndroidLoggingTest.kt
│                           ├── AndroidSocketAdapterTest.kt
│                           ├── BaseOkHttpClientUnitTest.kt
│                           ├── DisabledInitialiserTest.kt
│                           ├── NonRobolectricOkHttpClientTest.kt
│                           ├── RobolectricOkHttpClientTest.kt
│                           └── ShadowDnsResolver.kt
├── android-test-app/
│   ├── build.gradle.kts
│   ├── proguard-rules.pro
│   ├── src/
│   │   ├── androidTest/
│   │   │   └── kotlin/
│   │   │       └── okhttp/
│   │   │           └── android/
│   │   │               └── testapp/
│   │   │                   ├── IdnaTest.kt
│   │   │                   └── PublicSuffixDatabaseTest.kt
│   │   └── main/
│   │       ├── AndroidManifest.xml
│   │       ├── kotlin/
│   │       │   └── okhttp/
│   │       │       └── android/
│   │       │           └── testapp/
│   │       │               ├── MainActivity.kt
│   │       │               ├── MainActivity2.kt
│   │       │               └── TestApplication.kt
│   │       └── res/
│   │           ├── values/
│   │           │   └── strings.xml
│   │           └── xml/
│   │               └── network_security_config.xml
│   └── test-proguard-rules.pro
├── build-logic/
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src/
│       └── main/
│           └── kotlin/
│               ├── AlpnVersions.kt
│               ├── BndBuildAction.kt
│               ├── JavaModules.kt
│               ├── Osgi.kt
│               ├── okhttp.base-conventions.gradle.kts
│               ├── okhttp.dokka-multimodule-conventions.gradle.kts
│               ├── okhttp.jvm-conventions.gradle.kts
│               ├── okhttp.publish-conventions.gradle.kts
│               ├── okhttp.quality-conventions.gradle.kts
│               ├── okhttp.testing-conventions.gradle.kts
│               └── okhttp3/
│                   └── buildsupport/
│                       └── OkHttpBuildUtils.kt
├── build.gradle.kts
├── container-tests/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── containers/
│                       ├── BasicLoomTest.kt
│                       ├── BasicMockServerTest.kt
│                       ├── BasicProxyTest.kt
│                       └── SocksProxyTest.kt
├── deploy_website.sh
├── docs/
│   ├── assets/
│   │   └── css/
│   │       └── app.css
│   ├── changelogs/
│   │   ├── changelog_1x.md
│   │   ├── changelog_2x.md
│   │   ├── changelog_3x.md
│   │   ├── changelog_4x.md
│   │   └── upgrading_to_okhttp_4.md
│   ├── contribute/
│   │   ├── code_of_conduct.md
│   │   ├── concurrency.md
│   │   ├── contributing.md
│   │   └── debug_logging.md
│   ├── features/
│   │   ├── caching.md
│   │   ├── calls.md
│   │   ├── connections.md
│   │   ├── events.md
│   │   ├── https.md
│   │   ├── interceptors.md
│   │   └── r8_proguard.md
│   ├── recipes.md
│   ├── releasing.md
│   ├── security/
│   │   ├── security.md
│   │   ├── security_providers.md
│   │   └── tls_configuration_history.md
│   └── works_with_okhttp.md
├── fuzzing/
│   ├── fuzzingserver-config.json
│   ├── fuzzingserver-expected.txt
│   ├── fuzzingserver-test.sh
│   └── fuzzingserver-update-expected.sh
├── gradle/
│   ├── gradle-daemon-jvm.properties
│   ├── libs.versions.toml
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── maven-tests/
│   ├── .gitignore
│   ├── .mvn/
│   │   ├── jvm.config
│   │   ├── maven.config
│   │   └── wrapper/
│   │       └── maven-wrapper.properties
│   ├── mvnw
│   ├── mvnw.cmd
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── squareup/
│       │               └── okhttp3/
│       │                   └── maventest/
│       │                       └── SampleHttpClient.java
│       └── test/
│           └── java/
│               └── com/
│                   └── squareup/
│                       └── okhttp3/
│                           └── maventest/
│                               └── AppTest.java
├── mkdocs.yml
├── mockwebserver/
│   ├── Module.md
│   ├── README.md
│   ├── api/
│   │   └── mockwebserver3.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── mockwebserver3/
│       │           ├── Dispatcher.kt
│       │           ├── MockResponse.kt
│       │           ├── MockResponseBody.kt
│       │           ├── MockWebServer.kt
│       │           ├── PushPromise.kt
│       │           ├── QueueDispatcher.kt
│       │           ├── RecordedRequest.kt
│       │           ├── SocketEffect.kt
│       │           ├── SocketHandler.kt
│       │           └── internal/
│       │               ├── BufferMockResponseBody.kt
│       │               ├── MockWebServerSocket.kt
│       │               ├── RecordedRequestFactory.kt
│       │               ├── ThrottledSink.kt
│       │               └── TriggerSink.kt
│       └── test/
│           └── java/
│               └── mockwebserver3/
│                   ├── CustomDispatcherTest.kt
│                   ├── MockResponseSniTest.kt
│                   ├── MockWebServerTest.kt
│                   ├── RecordedRequestTest.kt
│                   └── internal/
│                       └── http2/
│                           └── Http2Server.kt
├── mockwebserver-deprecated/
│   ├── api/
│   │   └── mockwebserver.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── mockwebserver/
│       │               ├── DeprecationBridge.kt
│       │               ├── Dispatcher.kt
│       │               ├── MockResponse.kt
│       │               ├── MockWebServer.kt
│       │               ├── PushPromise.kt
│       │               ├── QueueDispatcher.kt
│       │               ├── RecordedRequest.kt
│       │               └── SocketPolicy.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── mockwebserver/
│                       ├── KotlinSourceModernTest.kt
│                       └── MockWebServerTest.kt
├── mockwebserver-junit4/
│   ├── README.md
│   ├── api/
│   │   └── mockwebserver3-junit4.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── mockwebserver3/
│       │           └── junit4/
│       │               └── MockWebServerRule.kt
│       └── test/
│           └── java/
│               └── mockwebserver3/
│                   └── junit4/
│                       └── MockWebServerRuleTest.kt
├── mockwebserver-junit5/
│   ├── README.md
│   ├── api/
│   │   └── mockwebserver3-junit5.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── mockwebserver3/
│       │           └── junit5/
│       │               ├── StartStop.kt
│       │               └── internal/
│       │                   └── StartStopExtension.kt
│       └── test/
│           └── java/
│               └── mockwebserver3/
│                   └── junit5/
│                       └── StartStopTest.kt
├── module-tests/
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── okhttp3/
│       │           └── modules/
│       │               ├── Main.java
│       │               └── OkHttpCaller.java
│       └── test/
│           └── java/
│               ├── module-info.java
│               └── okhttp3/
│                   └── modules/
│                       └── test/
│                           └── JavaModuleTest.java
├── native-image-tests/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       └── test/
│           ├── kotlin/
│           │   └── okhttp3/
│           │       └── nativeimage/
│           │           ├── PublicSuffixDatabaseTest.kt
│           │           ├── SampleTest.kt
│           │           └── WithArgumentSourceTest.kt
│           └── resources/
│               └── META-INF/
│                   └── native-image/
│                       └── okhttp/
│                           └── nit/
│                               └── resource-config.json
├── okcurl/
│   ├── README.md
│   ├── build.gradle.kts
│   ├── okcurl
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       └── curl/
│       │   │           ├── Main.kt
│       │   │           ├── MainCommandLine.kt
│       │   │           ├── internal/
│       │   │           │   └── -MainCommon.kt
│       │   │           └── logging/
│       │   │               ├── LoggingUtil.kt
│       │   │               ├── MessageFormatter.kt
│       │   │               └── OneLineLogFormat.kt
│       │   ├── resources/
│       │   │   └── META-INF/
│       │   │       └── native-image/
│       │   │           └── okhttp3/
│       │   │               └── okcurl/
│       │   │                   ├── reflect-config.json
│       │   │                   └── resource-config.json
│       │   └── resources-templates/
│       │       └── okcurl-version.properties
│       └── test/
│           └── kotlin/
│               └── okhttp3/
│                   └── curl/
│                       └── MainTest.kt
├── okhttp/
│   ├── Module.md
│   ├── api/
│   │   ├── android/
│   │   │   └── okhttp.api
│   │   └── jvm/
│   │       └── okhttp.api
│   ├── build.gradle.kts
│   ├── okhttp3.pro
│   └── src/
│       ├── androidHostTest/
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       └── internal/
│       │   │           └── publicsuffix/
│       │   │               └── PublicSuffixTesting.android.kt
│       │   └── resources/
│       │       └── okhttp3/
│       │           └── robolectric.properties
│       ├── androidMain/
│       │   ├── AndroidManifest.xml
│       │   ├── assets/
│       │   │   └── PublicSuffixDatabase.list
│       │   ├── baseline-prof.txt
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           ├── OkHttp.android.kt
│       │           └── internal/
│       │               ├── platform/
│       │               │   ├── Android10Platform.kt
│       │               │   ├── AndroidPlatform.kt
│       │               │   ├── ContextAwarePlatform.kt
│       │               │   ├── PlatformInitializer.kt
│       │               │   ├── PlatformRegistry.kt
│       │               │   └── android/
│       │               │       ├── Android10SocketAdapter.kt
│       │               │       ├── AndroidCertificateChainCleaner.kt
│       │               │       ├── AndroidLog.kt
│       │               │       ├── AndroidSocketAdapter.kt
│       │               │       ├── BouncyCastleSocketAdapter.kt
│       │               │       ├── ConscryptSocketAdapter.kt
│       │               │       ├── DeferredSocketAdapter.kt
│       │               │       ├── SocketAdapter.kt
│       │               │       └── StandardAndroidSocketAdapter.kt
│       │               └── publicsuffix/
│       │                   ├── AssetPublicSuffixList.kt
│       │                   └── PublicSuffixList.android.kt
│       ├── commonJvmAndroid/
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       ├── Address.kt
│       │   │       ├── Authenticator.kt
│       │   │       ├── Cache.kt
│       │   │       ├── CacheControl.kt
│       │   │       ├── Call.kt
│       │   │       ├── Callback.kt
│       │   │       ├── CertificatePinner.kt
│       │   │       ├── Challenge.kt
│       │   │       ├── CipherSuite.kt
│       │   │       ├── CompressionInterceptor.kt
│       │   │       ├── Connection.kt
│       │   │       ├── ConnectionPool.kt
│       │   │       ├── ConnectionSpec.kt
│       │   │       ├── Cookie.kt
│       │   │       ├── CookieJar.kt
│       │   │       ├── Credentials.kt
│       │   │       ├── Dispatcher.kt
│       │   │       ├── Dns.kt
│       │   │       ├── EventListener.kt
│       │   │       ├── FormBody.kt
│       │   │       ├── Gzip.kt
│       │   │       ├── Handshake.kt
│       │   │       ├── Headers.kt
│       │   │       ├── HttpUrl.kt
│       │   │       ├── Interceptor.kt
│       │   │       ├── MediaType.kt
│       │   │       ├── MultipartBody.kt
│       │   │       ├── MultipartReader.kt
│       │   │       ├── OkHttp.kt
│       │   │       ├── OkHttpClient.kt
│       │   │       ├── Protocol.kt
│       │   │       ├── Request.kt
│       │   │       ├── RequestBody.kt
│       │   │       ├── Response.kt
│       │   │       ├── ResponseBody.kt
│       │   │       ├── Route.kt
│       │   │       ├── TlsVersion.kt
│       │   │       ├── TrailersSource.kt
│       │   │       ├── WebSocket.kt
│       │   │       ├── WebSocketListener.kt
│       │   │       └── internal/
│       │   │           ├── -CacheControlCommon.kt
│       │   │           ├── -HeadersCommon.kt
│       │   │           ├── -HostnamesCommon.kt
│       │   │           ├── -NormalizeJvm.kt
│       │   │           ├── -UtilCommon.kt
│       │   │           ├── -UtilJvm.kt
│       │   │           ├── IsProbablyUtf8.kt
│       │   │           ├── NativeImageTestsAccessors.kt
│       │   │           ├── SuppressSignatureCheck.kt
│       │   │           ├── Tags.kt
│       │   │           ├── UnreadableResponseBody.kt
│       │   │           ├── authenticator/
│       │   │           │   └── JavaNetAuthenticator.kt
│       │   │           ├── cache/
│       │   │           │   ├── CacheInterceptor.kt
│       │   │           │   ├── CacheRequest.kt
│       │   │           │   ├── CacheStrategy.kt
│       │   │           │   ├── DiskLruCache.kt
│       │   │           │   └── FaultHidingSink.kt
│       │   │           ├── concurrent/
│       │   │           │   ├── Lockable.kt
│       │   │           │   ├── Task.kt
│       │   │           │   ├── TaskLogger.kt
│       │   │           │   ├── TaskQueue.kt
│       │   │           │   └── TaskRunner.kt
│       │   │           ├── connection/
│       │   │           │   ├── AddressPolicy.kt
│       │   │           │   ├── BufferedSocket.kt
│       │   │           │   ├── ConnectInterceptor.kt
│       │   │           │   ├── ConnectPlan.kt
│       │   │           │   ├── ConnectionListener.kt
│       │   │           │   ├── Exchange.kt
│       │   │           │   ├── ExchangeFinder.kt
│       │   │           │   ├── FailedPlan.kt
│       │   │           │   ├── FastFallbackExchangeFinder.kt
│       │   │           │   ├── ForceConnectRoutePlanner.kt
│       │   │           │   ├── InetAddressOrder.kt
│       │   │           │   ├── RealCall.kt
│       │   │           │   ├── RealConnection.kt
│       │   │           │   ├── RealConnectionPool.kt
│       │   │           │   ├── RealRoutePlanner.kt
│       │   │           │   ├── RetryTlsHandshake.kt
│       │   │           │   ├── ReusePlan.kt
│       │   │           │   ├── RouteDatabase.kt
│       │   │           │   ├── RoutePlanner.kt
│       │   │           │   ├── RouteSelector.kt
│       │   │           │   └── SequentialExchangeFinder.kt
│       │   │           ├── http/
│       │   │           │   ├── BridgeInterceptor.kt
│       │   │           │   ├── CallServerInterceptor.kt
│       │   │           │   ├── DateFormatting.kt
│       │   │           │   ├── ExchangeCodec.kt
│       │   │           │   ├── GzipRequestBody.kt
│       │   │           │   ├── HttpHeaders.kt
│       │   │           │   ├── HttpMethod.kt
│       │   │           │   ├── HttpStatusCodes.kt
│       │   │           │   ├── RealInterceptorChain.kt
│       │   │           │   ├── RealResponseBody.kt
│       │   │           │   ├── RequestLine.kt
│       │   │           │   ├── RetryAndFollowUpInterceptor.kt
│       │   │           │   └── StatusLine.kt
│       │   │           ├── http1/
│       │   │           │   ├── HeadersReader.kt
│       │   │           │   └── Http1ExchangeCodec.kt
│       │   │           ├── http2/
│       │   │           │   ├── ConnectionShutdownException.kt
│       │   │           │   ├── ErrorCode.kt
│       │   │           │   ├── FlowControlListener.kt
│       │   │           │   ├── Header.kt
│       │   │           │   ├── Hpack.kt
│       │   │           │   ├── Http2.kt
│       │   │           │   ├── Http2Connection.kt
│       │   │           │   ├── Http2ExchangeCodec.kt
│       │   │           │   ├── Http2Reader.kt
│       │   │           │   ├── Http2Stream.kt
│       │   │           │   ├── Http2Writer.kt
│       │   │           │   ├── Huffman.kt
│       │   │           │   ├── PushObserver.kt
│       │   │           │   ├── Settings.kt
│       │   │           │   ├── StreamResetException.kt
│       │   │           │   └── flowcontrol/
│       │   │           │       └── WindowCounter.kt
│       │   │           ├── idn/
│       │   │           │   ├── IdnaMappingTable.kt
│       │   │           │   └── Punycode.kt
│       │   │           ├── internal.kt
│       │   │           ├── platform/
│       │   │           │   ├── Jdk9Platform.kt
│       │   │           │   ├── Platform.kt
│       │   │           │   └── PlatformRegistry.kt
│       │   │           ├── proxy/
│       │   │           │   └── NullProxySelector.kt
│       │   │           ├── publicsuffix/
│       │   │           │   ├── BasePublicSuffixList.kt
│       │   │           │   ├── PublicSuffixDatabase.kt
│       │   │           │   ├── PublicSuffixList.kt
│       │   │           │   └── ResourcePublicSuffixList.kt
│       │   │           ├── tls/
│       │   │           │   ├── BasicCertificateChainCleaner.kt
│       │   │           │   ├── BasicTrustRootIndex.kt
│       │   │           │   ├── CertificateChainCleaner.kt
│       │   │           │   ├── OkHostnameVerifier.kt
│       │   │           │   └── TrustRootIndex.kt
│       │   │           ├── url/
│       │   │           │   └── -Url.kt
│       │   │           └── ws/
│       │   │               ├── MessageDeflater.kt
│       │   │               ├── MessageInflater.kt
│       │   │               ├── RealWebSocket.kt
│       │   │               ├── WebSocketExtensions.kt
│       │   │               ├── WebSocketProtocol.kt
│       │   │               ├── WebSocketReader.kt
│       │   │               └── WebSocketWriter.kt
│       │   └── kotlinTemplates/
│       │       └── okhttp3/
│       │           └── internal/
│       │               └── -InternalVersion.kt
│       ├── commonTest/
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           ├── CompressionInterceptorTest.kt
│       │           ├── OkHttpTest.kt
│       │           └── internal/
│       │               ├── IsProbablyUtf8Test.kt
│       │               └── publicsuffix/
│       │                   ├── ConfiguredPublicSuffixDatabaseTest.kt
│       │                   ├── ConfiguredPublicSuffixList.kt
│       │                   ├── PublicSuffixDatabaseTest.kt
│       │                   └── PublicSuffixTesting.kt
│       ├── jvmMain/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       ├── OkHttp.jvm.kt
│       │   │       └── internal/
│       │   │           ├── graal/
│       │   │           │   ├── GraalSvm.kt
│       │   │           │   └── OkHttpFeature.kt
│       │   │           ├── platform/
│       │   │           │   ├── BouncyCastlePlatform.kt
│       │   │           │   ├── ConscryptPlatform.kt
│       │   │           │   ├── Jdk8WithJettyBootPlatform.kt
│       │   │           │   ├── OpenJSSEPlatform.kt
│       │   │           │   └── PlatformRegistry.kt
│       │   │           └── publicsuffix/
│       │   │               └── PublicSuffixList.jvm.kt
│       │   └── resources/
│       │       ├── META-INF/
│       │       │   └── native-image/
│       │       │       └── okhttp/
│       │       │           └── okhttp/
│       │       │               ├── native-image.properties
│       │       │               ├── reflect-config.json
│       │       │               └── resource-config.json
│       │       └── okhttp3/
│       │           └── internal/
│       │               └── publicsuffix/
│       │                   └── PublicSuffixDatabase.list
│       ├── jvmTest/
│       │   ├── java/
│       │   │   └── okhttp3/
│       │   │       └── CallJavaTest.java
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       ├── AddressTest.kt
│       │   │       ├── AutobahnTester.kt
│       │   │       ├── BouncyCastleTest.kt
│       │   │       ├── CacheControlJvmTest.kt
│       │   │       ├── CacheControlTest.kt
│       │   │       ├── CacheCorruptionTest.kt
│       │   │       ├── CacheTest.kt
│       │   │       ├── CallHandshakeTest.kt
│       │   │       ├── CallKotlinTest.kt
│       │   │       ├── CallLimitsTest.kt
│       │   │       ├── CallTagsTest.kt
│       │   │       ├── CallTest.kt
│       │   │       ├── CertificateChainCleanerTest.kt
│       │   │       ├── CertificatePinnerKotlinTest.kt
│       │   │       ├── CertificatePinnerTest.kt
│       │   │       ├── ChannelSocketFactory.kt
│       │   │       ├── CipherSuiteTest.kt
│       │   │       ├── CommonRequestBodyTest.kt
│       │   │       ├── ConnectionCoalescingTest.kt
│       │   │       ├── ConnectionListenerTest.kt
│       │   │       ├── ConnectionReuseTest.kt
│       │   │       ├── ConnectionSpecTest.kt
│       │   │       ├── ConscryptTest.kt
│       │   │       ├── CookieTest.kt
│       │   │       ├── CookiesTest.kt
│       │   │       ├── CorrettoTest.kt
│       │   │       ├── DispatcherCleanupTest.kt
│       │   │       ├── DispatcherTest.kt
│       │   │       ├── DuplexTest.kt
│       │   │       ├── EventListenerTest.kt
│       │   │       ├── FakeRoutePlanner.kt
│       │   │       ├── FallbackTestClientSocketFactory.kt
│       │   │       ├── FastFallbackTest.kt
│       │   │       ├── FormBodyTest.kt
│       │   │       ├── HandshakeTest.kt
│       │   │       ├── HeadersChallengesTest.kt
│       │   │       ├── HeadersJvmTest.kt
│       │   │       ├── HeadersKotlinTest.kt
│       │   │       ├── HeadersRequestTest.kt
│       │   │       ├── HeadersTest.kt
│       │   │       ├── HttpUrlJvmTest.kt
│       │   │       ├── HttpUrlTest.kt
│       │   │       ├── InsecureForHostTest.kt
│       │   │       ├── InterceptorOverridesTest.kt
│       │   │       ├── InterceptorTest.kt
│       │   │       ├── JSSETest.kt
│       │   │       ├── KotlinDeprecationErrorTest.kt
│       │   │       ├── KotlinSourceModernTest.kt
│       │   │       ├── LoomTest.kt
│       │   │       ├── MediaTypeGetTest.kt
│       │   │       ├── MediaTypeJvmTest.kt
│       │   │       ├── MediaTypeTest.kt
│       │   │       ├── MultipartBodyTest.kt
│       │   │       ├── MultipartReaderTest.kt
│       │   │       ├── OkHttpClientTest.kt
│       │   │       ├── OpenJSSETest.kt
│       │   │       ├── ProtocolTest.kt
│       │   │       ├── PublicInternalApiTest.kt
│       │   │       ├── RecordedResponse.kt
│       │   │       ├── RecordingCallback.kt
│       │   │       ├── RecordingExecutor.kt
│       │   │       ├── RequestBodyTest.kt
│       │   │       ├── RequestCommonTest.kt
│       │   │       ├── RequestTest.kt
│       │   │       ├── ResponseBodyJvmTest.kt
│       │   │       ├── ResponseBodyTest.kt
│       │   │       ├── ResponseCommonTest.kt
│       │   │       ├── ResponseJvmTest.kt
│       │   │       ├── RouteFailureTest.kt
│       │   │       ├── ServerTruncatesRequestTest.kt
│       │   │       ├── SessionReuseTest.kt
│       │   │       ├── SocketChannelTest.kt
│       │   │       ├── SocksProxy.kt
│       │   │       ├── SocksProxyTest.kt
│       │   │       ├── TestLogHandler.kt
│       │   │       ├── TestTls13Request.kt
│       │   │       ├── TrailersTest.kt
│       │   │       ├── URLConnectionTest.kt
│       │   │       ├── UrlComponentEncodingTester.kt
│       │   │       ├── UrlComponentEncodingTesterJvm.kt
│       │   │       ├── WebPlatformToAsciiData.kt
│       │   │       ├── WebPlatformToAsciiTest.kt
│       │   │       ├── WebPlatformUrlTest.kt
│       │   │       ├── WebPlatformUrlTestData.kt
│       │   │       ├── WholeOperationTimeoutTest.kt
│       │   │       └── internal/
│       │   │           ├── DoubleInetAddressDns.kt
│       │   │           ├── HostnamesTest.kt
│       │   │           ├── RecordingAuthenticator.kt
│       │   │           ├── TagsTest.kt
│       │   │           ├── UtilTest.kt
│       │   │           ├── authenticator/
│       │   │           │   └── JavaNetAuthenticatorTest.kt
│       │   │           ├── cache/
│       │   │           │   └── DiskLruCacheTest.kt
│       │   │           ├── concurrent/
│       │   │           │   ├── TaskLoggerTest.kt
│       │   │           │   ├── TaskRunnerRealBackendTest.kt
│       │   │           │   └── TaskRunnerTest.kt
│       │   │           ├── connection/
│       │   │           │   ├── ConnectionPoolTest.kt
│       │   │           │   ├── FastFallbackExchangeFinderTest.kt
│       │   │           │   ├── InetAddressOrderTest.kt
│       │   │           │   ├── RetryConnectionTest.kt
│       │   │           │   └── RouteSelectorTest.kt
│       │   │           ├── http/
│       │   │           │   ├── CancelTest.kt
│       │   │           │   ├── ExternalHttp2Example.kt
│       │   │           │   ├── HttpDateTest.kt
│       │   │           │   ├── HttpUpgradesTest.kt
│       │   │           │   ├── SocketFailureTest.kt
│       │   │           │   ├── StatusLineTest.kt
│       │   │           │   └── ThreadInterruptTest.kt
│       │   │           ├── http2/
│       │   │           │   ├── BaseTestHandler.kt
│       │   │           │   ├── FrameLogTest.kt
│       │   │           │   ├── HpackTest.kt
│       │   │           │   ├── Http2ConnectionTest.kt
│       │   │           │   ├── Http2Test.kt
│       │   │           │   ├── HttpOverHttp2Test.kt
│       │   │           │   ├── HuffmanTest.kt
│       │   │           │   ├── MockHttp2Peer.kt
│       │   │           │   └── SettingsTest.kt
│       │   │           ├── idn/
│       │   │           │   ├── IdnaMappingTableTest.kt
│       │   │           │   └── PunycodeTest.kt
│       │   │           ├── io/
│       │   │           │   └── FaultyFileSystem.kt
│       │   │           ├── platform/
│       │   │           │   ├── Jdk8WithJettyBootPlatformTest.kt
│       │   │           │   ├── Jdk9PlatformTest.kt
│       │   │           │   └── PlatformTest.kt
│       │   │           ├── publicsuffix/
│       │   │           │   ├── PublicSuffixListGenerator.kt
│       │   │           │   └── PublicSuffixTesting.jvm.kt
│       │   │           ├── tls/
│       │   │           │   ├── CertificatePinnerChainValidationTest.kt
│       │   │           │   ├── ClientAuthTest.kt
│       │   │           │   └── HostnameVerifierTest.kt
│       │   │           └── ws/
│       │   │               ├── MessageDeflaterInflaterTest.kt
│       │   │               ├── RealWebSocketTest.kt
│       │   │               ├── WebSocketExtensionsTest.kt
│       │   │               ├── WebSocketHttpTest.kt
│       │   │               ├── WebSocketReaderTest.kt
│       │   │               ├── WebSocketRecorder.kt
│       │   │               └── WebSocketWriterTest.kt
│       │   └── resources/
│       │       ├── okhttp3/
│       │       │   └── internal/
│       │       │       └── publicsuffix/
│       │       │           └── NOTICE
│       │       ├── web-platform-test-toascii.json
│       │       └── web-platform-test-urltestdata.txt
│       └── main/
│           └── resources/
│               └── META-INF/
│                   └── native-image/
│                       └── okhttp/
│                           └── okhttp/
│                               └── native-image.properties
├── okhttp-bom/
│   └── build.gradle.kts
├── okhttp-brotli/
│   ├── README.md
│   ├── api/
│   │   └── okhttp-brotli.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── brotli/
│       │               ├── Brotli.kt
│       │               └── BrotliInterceptor.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── brotli/
│                       ├── BrotliInterceptorTest.kt
│                       └── BrotliTestMain.kt
├── okhttp-coroutines/
│   ├── Module.md
│   ├── README.md
│   ├── api/
│   │   └── okhttp-coroutines.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── coroutines/
│       │               └── ExecuteAsync.kt
│       └── test/
│           └── kotlin/
│               └── okhttp3/
│                   └── coroutines/
│                       └── ExecuteAsyncTest.kt
├── okhttp-dnsoverhttps/
│   ├── README.md
│   ├── api/
│   │   └── okhttp-dnsoverhttps.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── dnsoverhttps/
│       │               ├── BootstrapDns.kt
│       │               ├── DnsOverHttps.kt
│       │               └── DnsRecordCodec.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── dnsoverhttps/
│                       ├── DnsOverHttpsTest.kt
│                       ├── DnsRecordCodecTest.kt
│                       ├── DohProviders.kt
│                       └── TestDohMain.kt
├── okhttp-hpacktests/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── internal/
│                       └── http2/
│                           ├── HpackDecodeInteropTest.kt
│                           ├── HpackDecodeTestBase.kt
│                           ├── HpackRoundTripTest.kt
│                           └── hpackjson/
│                               ├── Case.kt
│                               ├── HpackJsonUtil.kt
│                               └── Story.kt
├── okhttp-idna-mapping-table/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       └── internal/
│       │   │           └── idn/
│       │   │               ├── GenerateIdnaMappingTableCode.kt
│       │   │               ├── IdnaMappingTableData.kt
│       │   │               ├── MappedRange.kt
│       │   │               ├── MappingTables.kt
│       │   │               └── SimpleIdnaMappingTable.kt
│       │   └── resources/
│       │       └── okhttp3/
│       │           └── internal/
│       │               └── idna/
│       │                   └── IdnaMappingTable.txt
│       └── test/
│           └── kotlin/
│               └── okhttp3/
│                   └── internal/
│                       └── idn/
│                           └── MappingTablesTest.kt
├── okhttp-java-net-cookiejar/
│   ├── README.md
│   ├── api/
│   │   └── okhttp-java-net-cookiejar.api
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           ├── java9/
│           │   └── module-info.java
│           └── kotlin/
│               └── okhttp3/
│                   └── java/
│                       └── net/
│                           └── cookiejar/
│                               └── JavaNetCookieJar.kt
├── okhttp-logging-interceptor/
│   ├── Module.md
│   ├── README.md
│   ├── api/
│   │   └── logging-interceptor.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── logging/
│       │               ├── HttpLoggingInterceptor.kt
│       │               └── LoggingEventListener.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── logging/
│                       ├── HttpLoggingInterceptorTest.kt
│                       └── LoggingEventListenerTest.kt
├── okhttp-osgi-tests/
│   ├── build.gradle.kts
│   └── src/
│       └── test/
│           └── kotlin/
│               └── okhttp3/
│                   └── osgi/
│                       └── OsgiTest.kt
├── okhttp-sse/
│   ├── Module.md
│   ├── README.md
│   ├── api/
│   │   └── okhttp-sse.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── sse/
│       │               ├── EventSource.kt
│       │               ├── EventSourceListener.kt
│       │               ├── EventSources.kt
│       │               └── internal/
│       │                   ├── RealEventSource.kt
│       │                   └── ServerSentEventReader.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── sse/
│                       └── internal/
│                           ├── Event.kt
│                           ├── EventSourceHttpTest.kt
│                           ├── EventSourceRecorder.kt
│                           ├── EventSourcesHttpTest.kt
│                           └── ServerSentEventIteratorTest.kt
├── okhttp-testing-support/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── okhttp3/
│       │   │       ├── CallEvent.kt
│       │   │       ├── ClientRuleEventListener.kt
│       │   │       ├── ConnectionEvent.kt
│       │   │       ├── DelegatingSSLSession.kt
│       │   │       ├── DelegatingSSLSocket.kt
│       │   │       ├── DelegatingSSLSocketFactory.kt
│       │   │       ├── DelegatingServerSocketFactory.kt
│       │   │       ├── DelegatingSocketFactory.kt
│       │   │       ├── EventListenerAdapter.kt
│       │   │       ├── EventListenerRelay.kt
│       │   │       ├── EventRecorder.kt
│       │   │       ├── FailingCall.kt
│       │   │       ├── FakeDns.kt
│       │   │       ├── FakeProxySelector.kt
│       │   │       ├── FakeSSLSession.kt
│       │   │       ├── ForwardingRequestBody.kt
│       │   │       ├── ForwardingResponseBody.kt
│       │   │       ├── JsseDebugLogging.kt
│       │   │       ├── OkHttpClientTestRule.kt
│       │   │       ├── OkHttpDebugLogging.kt
│       │   │       ├── RecordingConnectionListener.kt
│       │   │       ├── RecordingCookieJar.kt
│       │   │       ├── RecordingHostnameVerifier.kt
│       │   │       ├── SimpleProvider.kt
│       │   │       ├── SpecificHostSocketFactory.kt
│       │   │       ├── TestUtilCommon.kt
│       │   │       ├── TestUtilJvm.kt
│       │   │       ├── TestValueFactory.kt
│       │   │       ├── UppercaseRequestInterceptor.kt
│       │   │       ├── UppercaseResponseInterceptor.kt
│       │   │       ├── internal/
│       │   │       │   ├── RecordingOkAuthenticator.kt
│       │   │       │   ├── concurrent/
│       │   │       │   │   └── TaskFaker.kt
│       │   │       │   ├── duplex/
│       │   │       │   │   ├── AsyncRequestBody.kt
│       │   │       │   │   └── MockSocketHandler.kt
│       │   │       │   └── http/
│       │   │       │       └── RecordingProxySelector.kt
│       │   │       ├── okio/
│       │   │       │   └── LoggingFilesystem.kt
│       │   │       └── testing/
│       │   │           ├── Flaky.kt
│       │   │           ├── PlatformRule.kt
│       │   │           └── PlatformVersion.kt
│       │   └── resources/
│       │       └── META-INF/
│       │           └── proguard/
│       │               └── okhttp3.pro
│       └── test/
│           └── kotlin/
│               └── okhttp3/
│                   ├── OkHttpClientTestRuleTest.kt
│                   └── testing/
│                       └── PlatformRuleTest.kt
├── okhttp-tls/
│   ├── Module.md
│   ├── README.md
│   ├── api/
│   │   └── okhttp-tls.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java9/
│       │   │   └── module-info.java
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── tls/
│       │               ├── Certificates.kt
│       │               ├── HandshakeCertificates.kt
│       │               ├── HeldCertificate.kt
│       │               └── internal/
│       │                   ├── InsecureAndroidTrustManager.kt
│       │                   ├── InsecureExtendedTrustManager.kt
│       │                   ├── TlsUtil.kt
│       │                   └── der/
│       │                       ├── Adapters.kt
│       │                       ├── AnyValue.kt
│       │                       ├── BasicDerAdapter.kt
│       │                       ├── BitString.kt
│       │                       ├── Certificate.kt
│       │                       ├── CertificateAdapters.kt
│       │                       ├── DerAdapter.kt
│       │                       ├── DerHeader.kt
│       │                       ├── DerReader.kt
│       │                       ├── DerWriter.kt
│       │                       └── ObjectIdentifiers.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── tls/
│                       ├── CertificatesJavaTest.java
│                       ├── CertificatesTest.kt
│                       ├── HandshakeCertificatesTest.kt
│                       ├── HeldCertificateTest.kt
│                       └── internal/
│                           └── der/
│                               ├── DerCertificatesTest.kt
│                               └── DerTest.kt
├── okhttp-urlconnection/
│   ├── README.md
│   ├── api/
│   │   └── okhttp-urlconnection.api
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           ├── java9/
│           │   └── module-info.java
│           └── kotlin/
│               └── okhttp3/
│                   ├── JavaNetAuthenticator.kt
│                   └── JavaNetCookieJar.kt
├── okhttp-zstd/
│   ├── README.md
│   ├── api/
│   │   └── okhttp-zstd.api
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   └── kotlin/
│       │       └── okhttp3/
│       │           └── zstd/
│       │               └── Zstd.kt
│       └── test/
│           └── java/
│               └── okhttp3/
│                   └── zstd/
│                       ├── ZstdInterceptorJavaTest.java
│                       ├── ZstdInterceptorTest.kt
│                       └── ZstdTestMain.kt
├── regression-test/
│   ├── README.md
│   ├── build.gradle.kts
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── okhttp/
│       │           └── regression/
│       │               ├── IssueReproductionTest.java
│       │               ├── LetsEncryptTest.java
│       │               └── compare/
│       │                   ├── AndroidHttpEngineTest.kt
│       │                   ├── ApacheHttpClientHttp2Test.kt
│       │                   ├── ApacheHttpClientTest.kt
│       │                   └── OkHttpClientTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           └── res/
│               ├── values/
│               │   └── strings.xml
│               └── xml/
│                   └── network_security_config.xml
├── samples/
│   ├── compare/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── test/
│   │           └── kotlin/
│   │               └── okhttp3/
│   │                   └── compare/
│   │                       ├── ApacheHttpClientTest.kt
│   │                       ├── JavaHttpClientTest.kt
│   │                       ├── JettyHttpClientTest.kt
│   │                       └── OkHttpClientTest.kt
│   ├── crawler/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── okhttp3/
│   │                   └── sample/
│   │                       └── Crawler.java
│   ├── guide/
│   │   ├── README.md
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       └── okhttp3/
│   │       │           ├── guide/
│   │       │           │   ├── GetExample.java
│   │       │           │   └── PostExample.java
│   │       │           └── recipes/
│   │       │               ├── AccessHeaders.java
│   │       │               ├── AsynchronousGet.java
│   │       │               ├── Authenticate.java
│   │       │               ├── CacheResponse.java
│   │       │               ├── CancelCall.java
│   │       │               ├── CertificatePinning.java
│   │       │               ├── CheckHandshake.java
│   │       │               ├── ConfigureTimeouts.java
│   │       │               ├── CurrentDateHeader.java
│   │       │               ├── CustomCipherSuites.java
│   │       │               ├── CustomTrust.java
│   │       │               ├── HttpsServer.java
│   │       │               ├── LoggingInterceptors.java
│   │       │               ├── ParseResponseWithMoshi.java
│   │       │               ├── PerCallSettings.java
│   │       │               ├── PostFile.java
│   │       │               ├── PostForm.java
│   │       │               ├── PostMultipart.java
│   │       │               ├── PostStreaming.java
│   │       │               ├── PostStreamingWithPipe.java
│   │       │               ├── PostString.java
│   │       │               ├── PreemptiveAuth.java
│   │       │               ├── PrintEvents.java
│   │       │               ├── PrintEventsNonConcurrent.java
│   │       │               ├── Progress.java
│   │       │               ├── RequestBodyCompression.java
│   │       │               ├── RewriteResponseCacheControl.java
│   │       │               ├── SynchronousGet.java
│   │       │               ├── UploadProgress.java
│   │       │               ├── WebSocketEcho.java
│   │       │               └── kt/
│   │       │                   ├── AccessHeaders.kt
│   │       │                   ├── AsynchronousGet.kt
│   │       │                   ├── Authenticate.kt
│   │       │                   ├── CacheResponse.kt
│   │       │                   ├── CancelCall.kt
│   │       │                   ├── CertificatePinning.kt
│   │       │                   ├── ConfigureTimeouts.kt
│   │       │                   ├── CustomTrust.kt
│   │       │                   ├── DevServer.kt
│   │       │                   ├── ParseResponseWithMoshi.kt
│   │       │                   ├── PerCallSettings.kt
│   │       │                   ├── PostFile.kt
│   │       │                   ├── PostForm.kt
│   │       │                   ├── PostMultipart.kt
│   │       │                   ├── PostPath.kt
│   │       │                   ├── PostStreaming.kt
│   │       │                   ├── PostString.kt
│   │       │                   ├── SynchronousGet.kt
│   │       │                   ├── UploadProgress.kt
│   │       │                   ├── WiresharkExample.kt
│   │       │                   └── YubikeyClientAuth.kt
│   │       └── test/
│   │           └── kotlin/
│   │               └── okhttp3/
│   │                   └── AllMainsTest.kt
│   ├── simple-client/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── okhttp3/
│   │                   └── sample/
│   │                       └── OkHttpContributors.java
│   ├── slack/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── okhttp3/
│   │                   └── slack/
│   │                       ├── OAuthSession.java
│   │                       ├── OAuthSessionFactory.java
│   │                       ├── RtmSession.java
│   │                       ├── RtmStartResponse.java
│   │                       ├── SlackApi.java
│   │                       └── SlackClient.java
│   ├── static-server/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── okhttp3/
│   │                   └── sample/
│   │                       └── SampleServer.java
│   ├── tlssurvey/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           ├── kotlin/
│   │           │   └── okhttp3/
│   │           │       └── survey/
│   │           │           ├── CipherSuiteSurvey.kt
│   │           │           ├── Clients.kt
│   │           │           ├── Iana.kt
│   │           │           ├── RunSurvey.kt
│   │           │           ├── ssllabs/
│   │           │           │   ├── SslLabsApi.kt
│   │           │           │   ├── SslLabsClient.kt
│   │           │           │   └── UserAgentCapabilities.kt
│   │           │           └── types/
│   │           │               ├── Client.kt
│   │           │               └── SuiteId.kt
│   │           └── resources/
│   │               ├── okhttp_3.11.txt
│   │               ├── okhttp_3.13.txt
│   │               ├── okhttp_3.14.txt
│   │               ├── okhttp_3.9.txt
│   │               └── okhttp_4.10.txt
│   └── unixdomainsockets/
│       ├── build.gradle.kts
│       └── src/
│           └── main/
│               └── java/
│                   └── okhttp3/
│                       └── unixdomainsockets/
│                           ├── ClientAndServer.java
│                           ├── TunnelingUnixSocket.java
│                           ├── UnixDomainServerSocketFactory.java
│                           └── UnixDomainSocketFactory.java
├── settings.gradle.kts
└── test_docs.sh
Download .txt
SYMBOL INDEX (327 symbols across 56 files)

FILE: maven-tests/src/main/java/com/squareup/okhttp3/maventest/SampleHttpClient.java
  class SampleHttpClient (line 27) | public class SampleHttpClient {
    method SampleHttpClient (line 30) | public SampleHttpClient() {
    method makeCall (line 34) | public void makeCall(HttpUrl url) throws IOException {

FILE: maven-tests/src/test/java/com/squareup/okhttp3/maventest/AppTest.java
  class AppTest (line 28) | public class AppTest {
    method testApp (line 31) | @Test

FILE: module-tests/src/main/java/okhttp3/modules/Main.java
  class Main (line 24) | public class Main {
    method main (line 25) | public static void main(String[] args) throws IOException {

FILE: module-tests/src/main/java/okhttp3/modules/OkHttpCaller.java
  class OkHttpCaller (line 29) | public class OkHttpCaller {
    method callOkHttp (line 30) | public static Call callOkHttp(HttpUrl url) {

FILE: module-tests/src/test/java/okhttp3/modules/test/JavaModuleTest.java
  class JavaModuleTest (line 35) | class JavaModuleTest {
    method testVisibility (line 36) | @Test
    method testMockWebServer (line 42) | @Test
    method testModules (line 56) | @Test

FILE: okhttp-tls/src/test/java/okhttp3/tls/CertificatesJavaTest.java
  class CertificatesJavaTest (line 23) | public class CertificatesJavaTest {
    method testRoundtrip (line 24) | @Test

FILE: okhttp-zstd/src/test/java/okhttp3/zstd/ZstdInterceptorJavaTest.java
  class ZstdInterceptorJavaTest (line 23) | class ZstdInterceptorJavaTest {
    method testConstructor (line 24) | @Test

FILE: okhttp/src/jvmTest/java/okhttp3/CallJavaTest.java
  class CallJavaTest (line 22) | public class CallJavaTest {
    method tagsSeededFromRequest (line 28) | @Test
    method tagsCanBeComputed (line 43) | @Test

FILE: regression-test/src/androidTest/java/okhttp/regression/IssueReproductionTest.java
  class IssueReproductionTest (line 37) | @RunWith(AndroidJUnit4.class)
    method getFailsWithoutAdditionalCert (line 39) | @Test public void getFailsWithoutAdditionalCert() throws IOException {
    method sendRequest (line 45) | private void sendRequest(OkHttpClient client, String url) throws IOExc...

FILE: regression-test/src/androidTest/java/okhttp/regression/LetsEncryptTest.java
  class LetsEncryptTest (line 47) | @RunWith(AndroidJUnit4.class)
    method getFailsWithoutAdditionalCert (line 49) | @Test public void getFailsWithoutAdditionalCert() throws IOException {
    method getPassesAdditionalCert (line 63) | @Test public void getPassesAdditionalCert() throws IOException, Certif...
    method sendRequest (line 130) | private void sendRequest(OkHttpClient client, String url) throws IOExc...

FILE: regression-test/src/androidTest/java/okhttp/regression/compare/OkHttpClientTest.java
  class OkHttpClientTest (line 34) | @RunWith(AndroidJUnit4.class)
    method get (line 36) | @Test public void get() throws IOException {

FILE: samples/crawler/src/main/java/okhttp3/sample/Crawler.java
  class Crawler (line 43) | public final class Crawler {
    method Crawler (line 50) | public Crawler(OkHttpClient client, int queueLimit, int hostLimit) {
    method parallelDrainQueue (line 56) | private void parallelDrainQueue(int threadCount) {
    method drainQueue (line 70) | private void drainQueue() throws Exception {
    method fetch (line 89) | public void fetch(HttpUrl url) throws IOException {
    method main (line 130) | public static void main(String[] args) throws IOException {

FILE: samples/guide/src/main/java/okhttp3/guide/GetExample.java
  class GetExample (line 23) | public class GetExample {
    method run (line 26) | String run(String url) throws IOException {
    method main (line 36) | public static void main(String[] args) throws IOException {

FILE: samples/guide/src/main/java/okhttp3/guide/PostExample.java
  class PostExample (line 25) | public class PostExample {
    method post (line 30) | String post(String url, String json) throws IOException {
    method bowlingJson (line 41) | String bowlingJson(String player1, String player2) {
    method main (line 53) | public static void main(String[] args) throws IOException {

FILE: samples/guide/src/main/java/okhttp3/recipes/AccessHeaders.java
  class AccessHeaders (line 23) | public final class AccessHeaders {
    method run (line 26) | public void run() throws Exception {
    method main (line 43) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/AsynchronousGet.java
  class AsynchronousGet (line 27) | public final class AsynchronousGet {
    method run (line 30) | public void run() throws Exception {
    method main (line 55) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/Authenticate.java
  class Authenticate (line 24) | public final class Authenticate {
    method Authenticate (line 27) | public Authenticate() {
    method run (line 44) | public void run() throws Exception {
    method main (line 56) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/CacheResponse.java
  class CacheResponse (line 25) | public final class CacheResponse {
    method CacheResponse (line 28) | public CacheResponse(File cacheDirectory) throws Exception {
    method run (line 37) | public void run() throws Exception {
    method main (line 65) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/CancelCall.java
  class CancelCall (line 27) | public class CancelCall {
    method run (line 31) | public void run() throws Exception {
    method main (line 56) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/CertificatePinning.java
  class CertificatePinning (line 25) | public final class CertificatePinning {
    method run (line 33) | public void run() throws Exception {
    method main (line 47) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/CheckHandshake.java
  class CheckHandshake (line 28) | public final class CheckHandshake {
    method intercept (line 34) | @Override public Response intercept(Chain chain) throws IOException {
    method run (line 49) | public void run() throws Exception {
    method main (line 61) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/ConfigureTimeouts.java
  class ConfigureTimeouts (line 23) | public final class ConfigureTimeouts {
    method ConfigureTimeouts (line 26) | public ConfigureTimeouts() throws Exception {
    method run (line 35) | public void run() throws Exception {
    method main (line 45) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/CurrentDateHeader.java
  class CurrentDateHeader (line 26) | public final class CurrentDateHeader {
    method run (line 31) | public void run() throws Exception {
    class CurrentDateInterceptor (line 41) | static class CurrentDateInterceptor implements Interceptor {
      method intercept (line 42) | @Override public Response intercept(Chain chain) throws IOException {
    method main (line 55) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/CustomCipherSuites.java
  class CustomCipherSuites (line 42) | public final class CustomCipherSuites {
    method CustomCipherSuites (line 45) | public CustomCipherSuites() throws GeneralSecurityException {
    method defaultSslSocketFactory (line 78) | private SSLSocketFactory defaultSslSocketFactory(X509TrustManager trus...
    method defaultTrustManager (line 87) | private X509TrustManager defaultTrustManager() throws GeneralSecurityE...
    method javaNames (line 99) | private String[] javaNames(List<CipherSuite> cipherSuites) {
    class DelegatingSSLSocketFactory (line 111) | static class DelegatingSSLSocketFactory extends SSLSocketFactory {
      method DelegatingSSLSocketFactory (line 114) | DelegatingSSLSocketFactory(SSLSocketFactory delegate) {
      method getDefaultCipherSuites (line 118) | @Override public String[] getDefaultCipherSuites() {
      method getSupportedCipherSuites (line 122) | @Override public String[] getSupportedCipherSuites() {
      method createSocket (line 126) | @Override public Socket createSocket(
      method createSocket (line 131) | @Override public Socket createSocket(String host, int port) throws I...
      method createSocket (line 135) | @Override public Socket createSocket(
      method createSocket (line 140) | @Override public Socket createSocket(InetAddress host, int port) thr...
      method createSocket (line 144) | @Override public Socket createSocket(
      method configureSocket (line 150) | protected SSLSocket configureSocket(SSLSocket socket) throws IOExcep...
    method run (line 155) | public void run() throws Exception {
    method main (line 168) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java
  class CustomTrust (line 27) | public final class CustomTrust {
    method CustomTrust (line 128) | public CustomTrust() {
    method run (line 145) | public void run() throws Exception {
    method main (line 164) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/HttpsServer.java
  class HttpsServer (line 31) | public class HttpsServer {
    method run (line 32) | public void run() throws Exception {
    method main (line 58) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/LoggingInterceptors.java
  class LoggingInterceptors (line 25) | public final class LoggingInterceptors {
    method run (line 31) | public void run() throws Exception {
    class LoggingInterceptor (line 40) | private static class LoggingInterceptor implements Interceptor {
      method intercept (line 41) | @Override public Response intercept(Chain chain) throws IOException {
    method main (line 55) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/ParseResponseWithMoshi.java
  class ParseResponseWithMoshi (line 26) | public final class ParseResponseWithMoshi {
    method run (line 31) | public void run() throws Exception {
    class Gist (line 47) | static class Gist {
    class GistFile (line 51) | static class GistFile {
    method main (line 55) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/PerCallSettings.java
  class PerCallSettings (line 24) | public final class PerCallSettings {
    method run (line 27) | public void run() throws Exception {
    method main (line 53) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/PostFile.java
  class PostFile (line 26) | public final class PostFile {
    method run (line 32) | public void run() throws Exception {
    method main (line 47) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/PostForm.java
  class PostForm (line 25) | public final class PostForm {
    method run (line 28) | public void run() throws Exception {
    method main (line 44) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/PostMultipart.java
  class PostMultipart (line 27) | public final class PostMultipart {
    method run (line 37) | public void run() throws Exception {
    method main (line 61) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/PostStreaming.java
  class PostStreaming (line 26) | public final class PostStreaming {
    method run (line 32) | public void run() throws Exception {
    method main (line 67) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/PostStreamingWithPipe.java
  class PostStreamingWithPipe (line 28) | public final class PostStreamingWithPipe {
    method run (line 34) | public void run() throws Exception {
    method streamPrimesToSinkAsynchronously (line 51) | private void streamPrimesToSinkAsynchronously(final BufferedSink sink) {
    class PipeBody (line 85) | static final class PipeBody extends RequestBody {
      method sink (line 89) | public BufferedSink sink() {
      method contentType (line 93) | @Override public MediaType contentType() {
      method writeTo (line 97) | @Override public void writeTo(BufferedSink sink) throws IOException {
    method main (line 102) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/PostString.java
  class PostString (line 25) | public final class PostString {
    method run (line 31) | public void run() throws Exception {
    method main (line 52) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/PreemptiveAuth.java
  class PreemptiveAuth (line 25) | public final class PreemptiveAuth {
    method PreemptiveAuth (line 28) | public PreemptiveAuth() {
    method run (line 35) | public void run() throws Exception {
    method main (line 47) | public static void main(String... args) throws Exception {
    class BasicAuthInterceptor (line 51) | static final class BasicAuthInterceptor implements Interceptor {
      method BasicAuthInterceptor (line 55) | BasicAuthInterceptor(String host, String username, String password) {
      method intercept (line 60) | @Override public Response intercept(Chain chain) throws IOException {

FILE: samples/guide/src/main/java/okhttp3/recipes/PrintEvents.java
  class PrintEvents (line 36) | public final class PrintEvents {
    method run (line 41) | public void run() throws Exception {
    method main (line 73) | public static void main(String... args) throws Exception {
    class PrintingEventListener (line 77) | private static final class PrintingEventListener extends EventListener {
      method create (line 81) | @Override public EventListener create(Call call) {
      method PrintingEventListener (line 91) | PrintingEventListener(long callId, long callStartNanos) {
      method printEvent (line 96) | private void printEvent(String name) {
      method proxySelectStart (line 101) | @Override public void proxySelectStart(Call call, HttpUrl url) {
      method proxySelectEnd (line 105) | @Override public void proxySelectEnd(Call call, HttpUrl url, List<Pr...
      method callStart (line 109) | @Override public void callStart(Call call) {
      method dnsStart (line 113) | @Override public void dnsStart(Call call, String domainName) {
      method dnsEnd (line 117) | @Override public void dnsEnd(Call call, String domainName, List<Inet...
      method connectStart (line 121) | @Override public void connectStart(
      method secureConnectStart (line 126) | @Override public void secureConnectStart(Call call) {
      method secureConnectEnd (line 130) | @Override public void secureConnectEnd(Call call, Handshake handshak...
      method connectEnd (line 134) | @Override public void connectEnd(
      method connectFailed (line 139) | @Override public void connectFailed(Call call, InetSocketAddress ine...
      method connectionAcquired (line 144) | @Override public void connectionAcquired(Call call, Connection conne...
      method connectionReleased (line 148) | @Override public void connectionReleased(Call call, Connection conne...
      method requestHeadersStart (line 152) | @Override public void requestHeadersStart(Call call) {
      method requestHeadersEnd (line 156) | @Override public void requestHeadersEnd(Call call, Request request) {
      method requestBodyStart (line 160) | @Override public void requestBodyStart(Call call) {
      method requestBodyEnd (line 164) | @Override public void requestBodyEnd(Call call, long byteCount) {
      method requestFailed (line 168) | @Override public void requestFailed(Call call, IOException ioe) {
      method responseHeadersStart (line 172) | @Override public void responseHeadersStart(Call call) {
      method responseHeadersEnd (line 176) | @Override public void responseHeadersEnd(Call call, Response respons...
      method responseBodyStart (line 180) | @Override public void responseBodyStart(Call call) {
      method responseBodyEnd (line 184) | @Override public void responseBodyEnd(Call call, long byteCount) {
      method responseFailed (line 188) | @Override public void responseFailed(Call call, IOException ioe) {
      method callEnd (line 192) | @Override public void callEnd(Call call) {
      method callFailed (line 196) | @Override public void callFailed(Call call, IOException ioe) {
      method canceled (line 200) | @Override public void canceled(Call call) {

FILE: samples/guide/src/main/java/okhttp3/recipes/PrintEventsNonConcurrent.java
  class PrintEventsNonConcurrent (line 37) | public final class PrintEventsNonConcurrent {
    method run (line 42) | public void run() throws Exception {
    method main (line 60) | public static void main(String... args) throws Exception {
    class PrintingEventListener (line 64) | private static final class PrintingEventListener extends EventListener {
      method printEvent (line 67) | private void printEvent(String name) {
      method callStart (line 76) | @Override public void callStart(Call call) {
      method proxySelectStart (line 80) | @Override public void proxySelectStart(Call call, HttpUrl url) {
      method proxySelectEnd (line 84) | @Override public void proxySelectEnd(Call call, HttpUrl url, List<Pr...
      method dnsStart (line 88) | @Override public void dnsStart(Call call, String domainName) {
      method dnsEnd (line 92) | @Override public void dnsEnd(Call call, String domainName, List<Inet...
      method connectStart (line 96) | @Override public void connectStart(
      method secureConnectStart (line 101) | @Override public void secureConnectStart(Call call) {
      method secureConnectEnd (line 105) | @Override public void secureConnectEnd(Call call, Handshake handshak...
      method connectEnd (line 109) | @Override public void connectEnd(
      method connectFailed (line 114) | @Override public void connectFailed(Call call, InetSocketAddress ine...
      method connectionAcquired (line 119) | @Override public void connectionAcquired(Call call, Connection conne...
      method connectionReleased (line 123) | @Override public void connectionReleased(Call call, Connection conne...
      method requestHeadersStart (line 127) | @Override public void requestHeadersStart(Call call) {
      method requestHeadersEnd (line 131) | @Override public void requestHeadersEnd(Call call, Request request) {
      method requestBodyStart (line 135) | @Override public void requestBodyStart(Call call) {
      method requestBodyEnd (line 139) | @Override public void requestBodyEnd(Call call, long byteCount) {
      method requestFailed (line 143) | @Override public void requestFailed(Call call, IOException ioe) {
      method responseHeadersStart (line 147) | @Override public void responseHeadersStart(Call call) {
      method responseHeadersEnd (line 151) | @Override public void responseHeadersEnd(Call call, Response respons...
      method responseBodyStart (line 155) | @Override public void responseBodyStart(Call call) {
      method responseBodyEnd (line 159) | @Override public void responseBodyEnd(Call call, long byteCount) {
      method responseFailed (line 163) | @Override public void responseFailed(Call call, IOException ioe) {
      method callEnd (line 167) | @Override public void callEnd(Call call) {
      method callFailed (line 171) | @Override public void callFailed(Call call, IOException ioe) {
      method canceled (line 175) | @Override public void canceled(Call call) {

FILE: samples/guide/src/main/java/okhttp3/recipes/Progress.java
  class Progress (line 30) | public final class Progress {
    method run (line 32) | public void run() throws Exception {
    method main (line 78) | public static void main(String... args) throws Exception {
    class ProgressResponseBody (line 82) | private static class ProgressResponseBody extends ResponseBody {
      method ProgressResponseBody (line 88) | ProgressResponseBody(ResponseBody responseBody, ProgressListener pro...
      method contentType (line 93) | @Override public MediaType contentType() {
      method contentLength (line 97) | @Override public long contentLength() {
      method source (line 101) | @Override public BufferedSource source() {
      method source (line 108) | private Source source(Source source) {
    type ProgressListener (line 123) | interface ProgressListener {
      method update (line 124) | void update(long bytesRead, long contentLength, boolean done);

FILE: samples/guide/src/main/java/okhttp3/recipes/RequestBodyCompression.java
  class RequestBodyCompression (line 31) | public final class RequestBodyCompression {
    method run (line 48) | public void run() throws Exception {
    method main (line 65) | public static void main(String... args) throws Exception {
    class GzipRequestInterceptor (line 70) | static class GzipRequestInterceptor implements Interceptor {
      method intercept (line 71) | @Override public Response intercept(Chain chain) throws IOException {

FILE: samples/guide/src/main/java/okhttp3/recipes/RewriteResponseCacheControl.java
  class RewriteResponseCacheControl (line 26) | public final class RewriteResponseCacheControl {
    method RewriteResponseCacheControl (line 37) | public RewriteResponseCacheControl(File cacheDirectory) throws Excepti...
    method run (line 46) | public void run() throws Exception {
    method main (line 76) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/SynchronousGet.java
  class SynchronousGet (line 24) | public final class SynchronousGet {
    method run (line 27) | public void run() throws Exception {
    method main (line 44) | public static void main(String... args) throws Exception {

FILE: samples/guide/src/main/java/okhttp3/recipes/UploadProgress.java
  class UploadProgress (line 31) | public final class UploadProgress {
    method run (line 37) | public void run() throws Exception {
    method main (line 80) | public static void main(String... args) throws Exception {
    class ProgressRequestBody (line 84) | private static class ProgressRequestBody extends RequestBody {
      method ProgressRequestBody (line 89) | public ProgressRequestBody(RequestBody delegate, ProgressListener pr...
      method contentType (line 94) | @Override
      method contentLength (line 99) | @Override
      method writeTo (line 104) | @Override
      method sink (line 111) | public Sink sink(Sink sink) {
    type ProgressListener (line 135) | interface ProgressListener {
      method update (line 136) | void update(long bytesWritten, long contentLength, boolean done);

FILE: samples/guide/src/main/java/okhttp3/recipes/WebSocketEcho.java
  class WebSocketEcho (line 11) | public final class WebSocketEcho extends WebSocketListener {
    method run (line 12) | private void run() {
    method onOpen (line 26) | @Override public void onOpen(WebSocket webSocket, Response response) {
    method onMessage (line 33) | @Override public void onMessage(WebSocket webSocket, String text) {
    method onMessage (line 37) | @Override public void onMessage(WebSocket webSocket, ByteString bytes) {
    method onClosing (line 41) | @Override public void onClosing(WebSocket webSocket, int code, String ...
    method onFailure (line 46) | @Override public void onFailure(WebSocket webSocket, Throwable t, Resp...
    method main (line 50) | public static void main(String... args) {

FILE: samples/simple-client/src/main/java/okhttp3/sample/OkHttpContributors.java
  class OkHttpContributors (line 28) | public class OkHttpContributors {
    class Contributor (line 34) | static class Contributor {
    method main (line 39) | public static void main(String... args) throws Exception {
    method OkHttpContributors (line 63) | private OkHttpContributors() {

FILE: samples/slack/src/main/java/okhttp3/slack/OAuthSession.java
  class OAuthSession (line 19) | @SuppressWarnings("checkstyle:membername")
    method OAuthSession (line 28) | public OAuthSession(
    method toString (line 38) | @Override public String toString() {

FILE: samples/slack/src/main/java/okhttp3/slack/OAuthSessionFactory.java
  class OAuthSessionFactory (line 36) | public final class OAuthSessionFactory extends Dispatcher implements Clo...
    method OAuthSessionFactory (line 45) | public OAuthSessionFactory(SlackApi slackApi) {
    method start (line 49) | public void start() throws Exception {
    method newAuthorizeUrl (line 57) | public HttpUrl newAuthorizeUrl(String scopes, String team, Listener li...
    method randomToken (line 68) | private ByteString randomToken() {
    method redirectUrl (line 74) | private HttpUrl redirectUrl() {
    method dispatch (line 79) | @Override public MockResponse dispatch(RecordedRequest request) {
    type Listener (line 115) | public interface Listener {
      method sessionGranted (line 116) | void sessionGranted(OAuthSession session);
    method close (line 119) | @Override public void close() {

FILE: samples/slack/src/main/java/okhttp3/slack/RtmSession.java
  class RtmSession (line 25) | public final class RtmSession extends WebSocketListener implements Close...
    method RtmSession (line 31) | public RtmSession(SlackApi slackApi) {
    method open (line 35) | public void open(String accessToken) throws IOException {
    method onOpen (line 44) | @Override public synchronized void onOpen(WebSocket webSocket, Respons...
    method onMessage (line 49) | @Override public void onMessage(WebSocket webSocket, String text) {
    method onClosing (line 53) | @Override public void onClosing(WebSocket webSocket, int code, String ...
    method onFailure (line 58) | @Override public void onFailure(WebSocket webSocket, Throwable t, Resp...
    method close (line 63) | @Override public void close() throws IOException {

FILE: samples/slack/src/main/java/okhttp3/slack/RtmStartResponse.java
  class RtmStartResponse (line 22) | public final class RtmStartResponse {

FILE: samples/slack/src/main/java/okhttp3/slack/SlackApi.java
  class SlackApi (line 40) | public final class SlackApi {
    method SlackApi (line 49) | public SlackApi(String clientId, String clientSecret, int port) {
    method authorizeUrl (line 61) | public HttpUrl authorizeUrl(String scopes, HttpUrl redirectUrl, ByteSt...
    method exchangeCode (line 76) | public OAuthSession exchangeCode(String code, HttpUrl redirectUrl) thr...
    method rtmStart (line 94) | public RtmStartResponse rtmStart(String accessToken) throws IOException {
    method rtm (line 109) | public WebSocket rtm(HttpUrl url, WebSocketListener listener) {
    class SlackJsonAdapters (line 115) | static final class SlackJsonAdapters {
      method urlToJson (line 116) | @ToJson String urlToJson(HttpUrl httpUrl) {
      method urlFromJson (line 120) | @FromJson HttpUrl urlFromJson(String urlString) {

FILE: samples/slack/src/main/java/okhttp3/slack/SlackClient.java
  class SlackClient (line 24) | public final class SlackClient {
    method SlackClient (line 31) | public SlackClient(SlackApi slackApi) {
    method requestOauthSession (line 36) | public void requestOauthSession(String scopes, String team) throws Exc...
    method initOauthSession (line 51) | public synchronized void initOauthSession(OAuthSession session) {
    method awaitAccessToken (line 57) | public synchronized void awaitAccessToken(Timeout timeout) throws Inte...
    method startRtm (line 64) | public void startRtm() throws IOException {
    method main (line 74) | public static void main(String... args) throws Exception {

FILE: samples/static-server/src/main/java/okhttp3/sample/SampleServer.java
  class SampleServer (line 36) | public class SampleServer extends Dispatcher {
    method SampleServer (line 41) | public SampleServer(SSLContext sslContext, String root, int port) {
    method run (line 47) | public void run() throws IOException {
    method dispatch (line 54) | @Override public MockResponse dispatch(RecordedRequest request) {
    method directoryToResponse (line 76) | private MockResponse directoryToResponse(String basePath, File directo...
    method fileToResponse (line 94) | private MockResponse fileToResponse(String path, File file) throws IOE...
    method fileToBytes (line 101) | private Buffer fileToBytes(File file) throws IOException {
    method contentType (line 107) | private String contentType(String path) {
    method main (line 117) | public static void main(String[] args) throws Exception {
    method sslContext (line 133) | private static SSLContext sslContext(String keystoreFile, String passw...

FILE: samples/unixdomainsockets/src/main/java/okhttp3/unixdomainsockets/ClientAndServer.java
  class ClientAndServer (line 31) | public class ClientAndServer {
    method run (line 32) | public void run() throws Exception {
    method main (line 59) | public static void main(String... args) throws Exception {

FILE: samples/unixdomainsockets/src/main/java/okhttp3/unixdomainsockets/TunnelingUnixSocket.java
  class TunnelingUnixSocket (line 31) | final class TunnelingUnixSocket extends UnixSocket {
    method TunnelingUnixSocket (line 35) | TunnelingUnixSocket(File path, UnixSocketChannel channel) {
    method TunnelingUnixSocket (line 40) | TunnelingUnixSocket(File path, UnixSocketChannel channel, InetSocketAd...
    method connect (line 45) | @Override public void connect(SocketAddress endpoint) throws IOExcepti...
    method connect (line 50) | @Override public void connect(SocketAddress endpoint, int timeout) thr...
    method getInetAddress (line 55) | @Override public InetAddress getInetAddress() {

FILE: samples/unixdomainsockets/src/main/java/okhttp3/unixdomainsockets/UnixDomainServerSocketFactory.java
  class UnixDomainServerSocketFactory (line 33) | public final class UnixDomainServerSocketFactory extends ServerSocketFac...
    method UnixDomainServerSocketFactory (line 36) | public UnixDomainServerSocketFactory(File path) {
    method createServerSocket (line 40) | @Override public ServerSocket createServerSocket() throws IOException {
    method createServerSocket (line 44) | @Override public ServerSocket createServerSocket(int port) throws IOEx...
    method createServerSocket (line 48) | @Override public ServerSocket createServerSocket(int port, int backlog...
    method createServerSocket (line 52) | @Override public ServerSocket createServerSocket(
    class UnixDomainServerSocket (line 57) | final class UnixDomainServerSocket extends ServerSocket {
      method UnixDomainServerSocket (line 61) | UnixDomainServerSocket() throws IOException {
      method bind (line 64) | @Override public void bind(SocketAddress endpoint, int backlog) thro...
      method getLocalPort (line 73) | @Override public int getLocalPort() {
      method getLocalSocketAddress (line 77) | @Override public SocketAddress getLocalSocketAddress() {
      method accept (line 81) | @Override public Socket accept() throws IOException {
      method close (line 92) | @Override public void close() throws IOException {

FILE: samples/unixdomainsockets/src/main/java/okhttp3/unixdomainsockets/UnixDomainSocketFactory.java
  class UnixDomainSocketFactory (line 27) | public final class UnixDomainSocketFactory extends SocketFactory {
    method UnixDomainSocketFactory (line 30) | public UnixDomainSocketFactory(File path) {
    method createSocket (line 34) | @Override public Socket createSocket() throws IOException {
    method createSocket (line 39) | @Override public Socket createSocket(String host, int port) throws IOE...
    method createSocket (line 51) | @Override public Socket createSocket(
    method createSocket (line 56) | @Override public Socket createSocket(InetAddress host, int port) throw...
    method createSocket (line 68) | @Override public Socket createSocket(
Condensed preview — 783 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (6,222K chars).
[
  {
    "path": ".devcontainer/devcontainer.json",
    "chars": 429,
    "preview": "{\n  \"image\": \"mcr.microsoft.com/devcontainers/java:21-bookworm\",\n  \"features\": {\n      \"ghcr.io/devcontainers/features/j"
  },
  {
    "path": ".editorconfig",
    "chars": 185,
    "preview": "root = true\n\n[*]\nindent_size = 2\nij_continuation_indent_size = 2\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_"
  },
  {
    "path": ".gitattributes",
    "chars": 52,
    "preview": "* text=auto eol=lf\n\n*.bat text eol=crlf\n*.jar binary"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 1464,
    "preview": "Contributing\n============\n\nIf you would like to contribute code to OkHttp you can do so through GitHub by\nforking the re"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 410,
    "preview": "---\nname: Bug report\nabout: A reproducible problem\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\nGood bug reports include a "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 346,
    "preview": "---\nname: Feature request\nabout: Suggest an idea\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\nStart by telling us w"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "chars": 391,
    "preview": "---\nname: Question\nabout: Use Stack Overflow instead\ntitle: \"\\U0001F649\"\nlabels: ''\nassignees: ''\n\n---\n\n🛑 𝙎𝙏𝙊𝙋\n\nThis iss"
  },
  {
    "path": ".github/renovate.json",
    "chars": 1334,
    "preview": "{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"extends\": [\n    \"config:recommended\",\n    \"group:"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 11918,
    "preview": "name: build\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    types: [opened, labeled, unlabeled, synchroniz"
  },
  {
    "path": ".github/workflows/containers.yml",
    "chars": 875,
    "preview": "name: containers\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    types: [opened, labeled, unlabeled, synch"
  },
  {
    "path": ".github/workflows/docs.yml",
    "chars": 990,
    "preview": "name: docs\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    types: [opened, labeled, unlabeled, synchronize"
  },
  {
    "path": ".github/workflows/publish.yml",
    "chars": 787,
    "preview": "name: publish\n\non:\n  push:\n    tags:\n      - '**'\n\nenv:\n  GRADLE_OPTS: \"-Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon="
  },
  {
    "path": ".gitignore",
    "chars": 345,
    "preview": ".classpath\n.kotlin\n.project\n.settings\n.gradle\neclipsebin\n\nbin\ngen\nbuild\nout\nlib\ngenerated\n\ntarget\npom.xml.*\nrelease.prop"
  },
  {
    "path": ".gitmodules",
    "chars": 182,
    "preview": "[submodule \"okhttp-hpacktests/src/test/resources/hpack-test-case\"]\n\tpath = okhttp-hpacktests/src/test/resources/hpack-te"
  },
  {
    "path": ".junit.run/Not Slow.run.xml",
    "chars": 730,
    "preview": "<component name=\"ProjectRunConfigurationManager\">\n  <configuration default=\"false\" name=\"Not Slow\" type=\"JUnit\" factoryN"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 116,
    "preview": "{\n    \"java.configuration.updateBuildConfiguration\": \"interactive\",\n    \"java.import.gradle.wrapper.enabled\": true\n}"
  },
  {
    "path": "BUG-BOUNTY.md",
    "chars": 372,
    "preview": "Serious about security\n======================\n\nSquare recognizes the important contributions the security research commu"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 36988,
    "preview": "Change Log\n==========\n\n## Version 5.3.2\n\n_2025-11-18_\n\n *  Fix: Don't delay triggering timeouts. In Okio 3.16.0 we intro"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2051,
    "preview": "Contributing\n============\n\nKeeping the project small and stable limits our ability to accept new contributors. We are no"
  },
  {
    "path": "LICENSE.txt",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "README.md",
    "chars": 9733,
    "preview": "OkHttp\n======\n\nSee the [project website][okhttp] for documentation and APIs.\n\nHTTP is the way modern applications networ"
  },
  {
    "path": "android-test/build.gradle.kts",
    "chars": 3857,
    "preview": "import okhttp3.buildsupport.androidBuild\n\nplugins {\n  id(\"okhttp.base-conventions\")\n  id(\"com.android.library\")\n  id(\"de"
  },
  {
    "path": "android-test/src/androidDeviceTest/README.md",
    "chars": 2524,
    "preview": "Android Test\n============\n\nA gradle module for running Android instrumentation tests on a device or emulator.\n\n1. Add an"
  },
  {
    "path": "android-test/src/androidDeviceTest/java/okhttp/android/test/OkHttpTest.kt",
    "chars": 30619,
    "preview": "/*\n * Copyright (C) 2019 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "android-test/src/androidDeviceTest/java/okhttp/android/test/SingleAndroidTest.kt",
    "chars": 2198,
    "preview": "/*\n * Copyright (C) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test/src/androidDeviceTest/java/okhttp/android/test/StrictModeTest.kt",
    "chars": 2217,
    "preview": "/*\n * Copyright (C) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test/src/androidDeviceTest/java/okhttp/android/test/alpn/AlpnOverrideTest.kt",
    "chars": 2826,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "android-test/src/androidDeviceTest/java/okhttp/android/test/letsencrypt/LetsEncryptClientTest.kt",
    "chars": 4483,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "android-test/src/androidDeviceTest/java/okhttp/android/test/sni/SniOverrideTest.kt",
    "chars": 3702,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "android-test/src/main/AndroidManifest.xml",
    "chars": 387,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          xmlns:tools=\"http://schemas.android.com/t"
  },
  {
    "path": "android-test/src/main/res/values/strings.xml",
    "chars": 73,
    "preview": "<resources>\n  <string name=\"app_name\">android-test</string>\n</resources>\n"
  },
  {
    "path": "android-test/src/main/res/xml/network_security_config.xml",
    "chars": 158,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<network-security-config>\n  <base-config cleartextTrafficPermitted=\"false\">\n  </b"
  },
  {
    "path": "android-test/src/test/kotlin/okhttp/android/test/AndroidLoggingTest.kt",
    "chars": 3301,
    "preview": "/*\n * Copyright (c) 2022 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "android-test/src/test/kotlin/okhttp/android/test/AndroidSocketAdapterTest.kt",
    "chars": 3665,
    "preview": "/*\n * Copyright (C) 2019 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "android-test/src/test/kotlin/okhttp/android/test/BaseOkHttpClientUnitTest.kt",
    "chars": 2343,
    "preview": "/*\n * Copyright (c) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test/src/test/kotlin/okhttp/android/test/DisabledInitialiserTest.kt",
    "chars": 2125,
    "preview": "/*\n * Copyright (c) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test/src/test/kotlin/okhttp/android/test/NonRobolectricOkHttpClientTest.kt",
    "chars": 1607,
    "preview": "/*\n * Copyright (c) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test/src/test/kotlin/okhttp/android/test/RobolectricOkHttpClientTest.kt",
    "chars": 1256,
    "preview": "/*\n * Copyright (c) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test/src/test/kotlin/okhttp/android/test/ShadowDnsResolver.kt",
    "chars": 1715,
    "preview": "/*\n * Copyright (C) 2024 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test-app/build.gradle.kts",
    "chars": 1260,
    "preview": "@file:Suppress(\"UnstableApiUsage\")\n\nimport okhttp3.buildsupport.testJavaVersion\n\n\nplugins {\n  id(\"okhttp.base-convention"
  },
  {
    "path": "android-test-app/proguard-rules.pro",
    "chars": 100,
    "preview": "# no rules should be needed\n\n-whyareyoukeeping class okhttp3.internal.idn.IdnaMappingTable {\n  *;\n}\n"
  },
  {
    "path": "android-test-app/src/androidTest/kotlin/okhttp/android/testapp/IdnaTest.kt",
    "chars": 867,
    "preview": "/*\n * Copyright (c) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test-app/src/androidTest/kotlin/okhttp/android/testapp/PublicSuffixDatabaseTest.kt",
    "chars": 1060,
    "preview": "/*\n * Copyright (C) 2023 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test-app/src/main/AndroidManifest.xml",
    "chars": 992,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          xmlns:tools=\"http://schemas.android.com/t"
  },
  {
    "path": "android-test-app/src/main/kotlin/okhttp/android/testapp/MainActivity.kt",
    "chars": 1715,
    "preview": "/*\n * Copyright (C) 2023 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test-app/src/main/kotlin/okhttp/android/testapp/MainActivity2.kt",
    "chars": 669,
    "preview": "/*\n * Copyright (C) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test-app/src/main/kotlin/okhttp/android/testapp/TestApplication.kt",
    "chars": 1361,
    "preview": "/*\n * Copyright (C) 2023 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "android-test-app/src/main/res/values/strings.xml",
    "chars": 73,
    "preview": "<resources>\n  <string name=\"app_name\">android-test</string>\n</resources>\n"
  },
  {
    "path": "android-test-app/src/main/res/xml/network_security_config.xml",
    "chars": 159,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<network-security-config>\n  <base-config cleartextTrafficPermitted=\"false\">\n  </b"
  },
  {
    "path": "android-test-app/test-proguard-rules.pro",
    "chars": 13,
    "preview": "-dontwarn **\n"
  },
  {
    "path": "build-logic/build.gradle.kts",
    "chars": 1082,
    "preview": "plugins {\n  `kotlin-dsl`\n  id(\"com.diffplug.spotless\") version \"8.4.0\"\n}\n\nconfigure<com.diffplug.gradle.spotless.Spotles"
  },
  {
    "path": "build-logic/settings.gradle.kts",
    "chars": 434,
    "preview": "@file:Suppress(\"UnstableApiUsage\")\n\npluginManagement {\n  repositories {\n    mavenCentral()\n    gradlePluginPortal()\n    "
  },
  {
    "path": "build-logic/src/main/kotlin/AlpnVersions.kt",
    "chars": 1799,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "build-logic/src/main/kotlin/BndBuildAction.kt",
    "chars": 9104,
    "preview": "/*\n * Copyright (c) aQute SARL (2000, 2021). All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 ("
  },
  {
    "path": "build-logic/src/main/kotlin/JavaModules.kt",
    "chars": 2365,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "build-logic/src/main/kotlin/Osgi.kt",
    "chars": 3587,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "build-logic/src/main/kotlin/okhttp.base-conventions.gradle.kts",
    "chars": 1938,
    "preview": "import org.gradle.api.artifacts.VersionCatalogsExtension\nimport okhttp3.buildsupport.platform\nimport okhttp3.buildsuppor"
  },
  {
    "path": "build-logic/src/main/kotlin/okhttp.dokka-multimodule-conventions.gradle.kts",
    "chars": 822,
    "preview": "val okhttpDokka: String? by project\nval dokkaBuild = okhttpDokka?.toBoolean() == true\n\nif (dokkaBuild) {\n  apply(plugin "
  },
  {
    "path": "build-logic/src/main/kotlin/okhttp.jvm-conventions.gradle.kts",
    "chars": 1455,
    "preview": "import org.jetbrains.kotlin.gradle.dsl.JvmTarget\nimport org.jetbrains.kotlin.gradle.tasks.KotlinCompile\nimport tapmoc.Ta"
  },
  {
    "path": "build-logic/src/main/kotlin/okhttp.publish-conventions.gradle.kts",
    "chars": 2704,
    "preview": "import com.vanniktech.maven.publish.JavadocJar\nimport com.vanniktech.maven.publish.KotlinJvm\nimport com.vanniktech.maven"
  },
  {
    "path": "build-logic/src/main/kotlin/okhttp.quality-conventions.gradle.kts",
    "chars": 2919,
    "preview": "import com.vanniktech.maven.publish.MavenPublishBaseExtension\nimport ru.vyarus.gradle.plugin.animalsniffer.AnimalSniffer"
  },
  {
    "path": "build-logic/src/main/kotlin/okhttp.testing-conventions.gradle.kts",
    "chars": 1775,
    "preview": "import org.gradle.api.tasks.testing.logging.TestExceptionFormat\nimport org.gradle.api.artifacts.VersionCatalogsExtension"
  },
  {
    "path": "build-logic/src/main/kotlin/okhttp3/buildsupport/OkHttpBuildUtils.kt",
    "chars": 1064,
    "preview": "/*\n * Copyright (c) 2026 OkHttp Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may"
  },
  {
    "path": "build.gradle.kts",
    "chars": 839,
    "preview": "plugins {\n  alias(libs.plugins.spotless) apply false\n  alias(libs.plugins.android.library) apply false\n  alias(libs.plug"
  },
  {
    "path": "container-tests/README.md",
    "chars": 113,
    "preview": "OkHttp Container Tests\n======================\n\nThis module contains tests against other services\nvia containers.\n"
  },
  {
    "path": "container-tests/build.gradle.kts",
    "chars": 1296,
    "preview": "plugins {\n  kotlin(\"jvm\")\n  id(\"okhttp.base-conventions\")\n}\n\nimport okhttp3.buildsupport.platform\nimport okhttp3.buildsu"
  },
  {
    "path": "container-tests/src/test/java/okhttp3/containers/BasicLoomTest.kt",
    "chars": 3742,
    "preview": "/*\n * Copyright (C) 2024 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "container-tests/src/test/java/okhttp3/containers/BasicMockServerTest.kt",
    "chars": 3442,
    "preview": "/*\n * Copyright (C) 2024 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "container-tests/src/test/java/okhttp3/containers/BasicProxyTest.kt",
    "chars": 6385,
    "preview": "/*\n * Copyright (C) 2024 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "container-tests/src/test/java/okhttp3/containers/SocksProxyTest.kt",
    "chars": 2709,
    "preview": "/*\n * Copyright (C) 2024 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "deploy_website.sh",
    "chars": 1265,
    "preview": "#!/bin/bash\n\n# The website is built using MkDocs with the Material theme.\n# https://squidfunk.github.io/mkdocs-material/"
  },
  {
    "path": "docs/assets/css/app.css",
    "chars": 1128,
    "preview": "@font-face {\n    font-family: cash-market;\n    src: url(\"https://cash-f.squarecdn.com/static/fonts/cash-market/v2/CashMa"
  },
  {
    "path": "docs/changelogs/changelog_1x.md",
    "chars": 6567,
    "preview": "OkHttp 1.x Change Log\n=====================\n\n## Version 1.6.0\n\n_2014-05-23_\n\n * Offer bridges to make it easier to migra"
  },
  {
    "path": "docs/changelogs/changelog_2x.md",
    "chars": 27214,
    "preview": "OkHttp 2.x Change Log\n=====================\n\n## Version 2.7.5\n\n_2016-02-25_\n\n *  Fix: Change the certificate pinner to a"
  },
  {
    "path": "docs/changelogs/changelog_3x.md",
    "chars": 52008,
    "preview": "OkHttp 3.x Change Log\n=====================\n\n## Version 3.14.9\n\n_2020-05-17_\n\n *  Fix: Don't crash when running as a plu"
  },
  {
    "path": "docs/changelogs/changelog_4x.md",
    "chars": 25773,
    "preview": "OkHttp 4.x Change Log\n=====================\n\n## Version 4.12.0\n\n_2023-10-16_\n\n *  Fix: Don't hang taking headers for HTT"
  },
  {
    "path": "docs/changelogs/upgrading_to_okhttp_4.md",
    "chars": 11132,
    "preview": "Upgrading to OkHttp 4\n=====================\n\nOkHttp 4.x upgrades our implementation language from Java to Kotlin and kee"
  },
  {
    "path": "docs/contribute/code_of_conduct.md",
    "chars": 5180,
    "preview": "Open Source Code of Conduct\n===========================\n\nAt Square, we are committed to contributing to the open source "
  },
  {
    "path": "docs/contribute/concurrency.md",
    "chars": 7130,
    "preview": "Concurrency\n===========\n\nThis document describes the concurrency considerations for http/2 connections and the connectio"
  },
  {
    "path": "docs/contribute/contributing.md",
    "chars": 2051,
    "preview": "Contributing\n============\n\nKeeping the project small and stable limits our ability to accept new contributors. We are no"
  },
  {
    "path": "docs/contribute/debug_logging.md",
    "chars": 2779,
    "preview": "Debug Logging\n=============\n\nOkHttp has internal APIs to enable debug logging. It uses the `java.util.logging` API which"
  },
  {
    "path": "docs/features/caching.md",
    "chars": 3188,
    "preview": "Caching\n=======\n\nOkHttp implements an optional, off by default, Cache. OkHttp aims for RFC correct and\npragmatic caching"
  },
  {
    "path": "docs/features/calls.md",
    "chars": 3972,
    "preview": "# Calls\n\nThe HTTP client’s job is to accept your request and produce its response. This is simple in theory but it gets "
  },
  {
    "path": "docs/features/connections.md",
    "chars": 5550,
    "preview": "Connections\n===========\n\nAlthough you provide only the URL, OkHttp plans its connection to your webserver using three ty"
  },
  {
    "path": "docs/features/events.md",
    "chars": 7864,
    "preview": "Events\n======\n\nEvents allow you to capture metrics on your application’s HTTP calls. Use events to monitor:\n\n * The size"
  },
  {
    "path": "docs/features/https.md",
    "chars": 10727,
    "preview": "HTTPS\n=====\n\nOkHttp attempts to balance two competing concerns:\n\n * **Connectivity** to as many hosts as possible. That "
  },
  {
    "path": "docs/features/interceptors.md",
    "chars": 8297,
    "preview": "Interceptors\n============\n\nInterceptors are a powerful mechanism that can monitor, rewrite, and retry calls. Here's a si"
  },
  {
    "path": "docs/features/r8_proguard.md",
    "chars": 570,
    "preview": "\nR8 / ProGuard\n=============\n\nIf you use OkHttp as a dependency in an Android project which uses R8 as a default compile"
  },
  {
    "path": "docs/recipes.md",
    "chars": 48975,
    "preview": "---\ntitle: Recipes\ndescription: A collection of common/useful code examples for Kotlin and Java\n---\n\n\n# Recipes\n\nWe've w"
  },
  {
    "path": "docs/releasing.md",
    "chars": 1117,
    "preview": "Releasing\n=========\n\n1. Update `CHANGELOG.md`.\n\n2. Set versions:\n\n    ```\n    export RELEASE_VERSION=X.Y.Z\n    export NE"
  },
  {
    "path": "docs/security/security.md",
    "chars": 1449,
    "preview": "Security\n========\n\n## Supported Versions\n\n| Version | Supported           | Notes                                       "
  },
  {
    "path": "docs/security/security_providers.md",
    "chars": 1755,
    "preview": "\nSecurity Providers\n==================\n\n## Provider Status\n\n| Provider         | HTTP/2  | TLSv1.3      | Powered By    "
  },
  {
    "path": "docs/security/tls_configuration_history.md",
    "chars": 9168,
    "preview": "TLS Configuration History\n=========================\n\nOkHttp tracks the dynamic TLS ecosystem to balance connectivity and"
  },
  {
    "path": "docs/works_with_okhttp.md",
    "chars": 3863,
    "preview": "Works with OkHttp\n=================\n\nHere’s some libraries that work nicely with OkHttp.\n\n * [Chucker](https://github.co"
  },
  {
    "path": "fuzzing/fuzzingserver-config.json",
    "chars": 2171,
    "preview": "{\n  \"url\": \"ws://127.0.0.1:9099\",\n  \"outdir\": \"./target/fuzzingserver-report\",\n  \"cases\": [\"*\"],\n  \"exclude-cases\": [\n  "
  },
  {
    "path": "fuzzing/fuzzingserver-expected.txt",
    "chars": 6869,
    "preview": "\"1.1.1 OK\"\n\"1.1.2 OK\"\n\"1.1.3 OK\"\n\"1.1.4 OK\"\n\"1.1.5 OK\"\n\"1.1.6 OK\"\n\"1.1.7 OK\"\n\"1.1.8 OK\"\n\"1.2.1 OK\"\n\"1.2.2 OK\"\n\"1.2.3 OK\""
  },
  {
    "path": "fuzzing/fuzzingserver-test.sh",
    "chars": 673,
    "preview": "#!/usr/bin/env bash\n\nSCRIPT_DIR=\"$( cd \"$( dirname \"$0\" )\" && pwd )\"\ncd \"$SCRIPT_DIR\"\n\nwhich wstest\nif [ $? != 0 ]; then"
  },
  {
    "path": "fuzzing/fuzzingserver-update-expected.sh",
    "chars": 275,
    "preview": "#!/usr/bin/env bash\n\nSCRIPT_DIR=\"$( cd \"$( dirname \"$0\" )\" && pwd )\"\ncd \"$SCRIPT_DIR\"\n\nif [ ! -f target/fuzzingserver-ac"
  },
  {
    "path": "gradle/gradle-daemon-jvm.properties",
    "chars": 88,
    "preview": "#This file is generated by updateDaemonJvm\ntoolchainVendor=ADOPTIUM\ntoolchainVersion=21\n"
  },
  {
    "path": "gradle/libs.versions.toml",
    "chars": 12267,
    "preview": "[versions]\nagp = \"9.1.0\"\namazon-corretto = \"2.5.0\"\nandroid-junit5 = \"2.0.1\"\nandroidx-activity = \"1.11.0\"\nandroidx-annota"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 252,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
  },
  {
    "path": "gradle.properties",
    "chars": 751,
    "preview": "org.gradle.caching=true\norg.gradle.parallel=true\n\n# Enable configuration cache\norg.gradle.configuration-cache=true\norg.g"
  },
  {
    "path": "gradlew",
    "chars": 8631,
    "preview": "#!/bin/sh\n\n#\n# Copyright © 2015 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "gradlew.bat",
    "chars": 2896,
    "preview": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (th"
  },
  {
    "path": "maven-tests/.gitignore",
    "chars": 7,
    "preview": "target\n"
  },
  {
    "path": "maven-tests/.mvn/jvm.config",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "maven-tests/.mvn/maven.config",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "maven-tests/.mvn/wrapper/maven-wrapper.properties",
    "chars": 961,
    "preview": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE f"
  },
  {
    "path": "maven-tests/mvnw",
    "chars": 10665,
    "preview": "#!/bin/sh\n# ----------------------------------------------------------------------------\n# Licensed to the Apache Softwa"
  },
  {
    "path": "maven-tests/mvnw.cmd",
    "chars": 6912,
    "preview": "<# : batch portion\n@REM ----------------------------------------------------------------------------\n@REM Licensed to th"
  },
  {
    "path": "maven-tests/pom.xml",
    "chars": 1822,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/"
  },
  {
    "path": "maven-tests/src/main/java/com/squareup/okhttp3/maventest/SampleHttpClient.java",
    "chars": 1176,
    "preview": "/*\n * Copyright (C) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "maven-tests/src/test/java/com/squareup/okhttp3/maventest/AppTest.java",
    "chars": 1148,
    "preview": "/*\n * Copyright (C) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mkdocs.yml",
    "chars": 3949,
    "preview": "site_name: OkHttp\nsite_url: https://square.github.io/okhttp/\nrepo_name: OkHttp\nrepo_url: https://github.com/square/okhtt"
  },
  {
    "path": "mockwebserver/Module.md",
    "chars": 74,
    "preview": "# Module mockwebserver\n\nA scriptable web server for testing HTTP clients.\n"
  },
  {
    "path": "mockwebserver/README.md",
    "chars": 8343,
    "preview": "MockWebServer\n=============\n\nA scriptable web server for testing HTTP clients\n\n\n### Motivation\n\nThis library makes it ea"
  },
  {
    "path": "mockwebserver/api/mockwebserver3.api",
    "chars": 12038,
    "preview": "public abstract class mockwebserver3/Dispatcher : java/io/Closeable {\n\tpublic fun <init> ()V\n\tpublic fun close ()V\n\tpubl"
  },
  {
    "path": "mockwebserver/build.gradle.kts",
    "chars": 591,
    "preview": "plugins {\n  kotlin(\"jvm\")\n  id(\"okhttp.publish-conventions\")\n  id(\"okhttp.jvm-conventions\")\n  id(\"okhttp.quality-convent"
  },
  {
    "path": "mockwebserver/src/main/java9/module-info.java",
    "chars": 125,
    "preview": "@SuppressWarnings(\"module\")\nmodule mockwebserver3 {\n  requires okhttp3;\n  exports mockwebserver3;\n  requires java.loggin"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/Dispatcher.kt",
    "chars": 1668,
    "preview": "/*\n * Copyright (C) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/MockResponse.kt",
    "chars": 18242,
    "preview": "/*\n * Copyright (C) 2011 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/MockResponseBody.kt",
    "chars": 1052,
    "preview": "/*\n * Copyright (c) 2022 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/MockWebServer.kt",
    "chars": 41291,
    "preview": "/*\n * Copyright (C) 2011 Google Inc.\n * Copyright (C) 2013 Square, Inc.\n *\n * Licensed under the Apache License, Version"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/PushPromise.kt",
    "chars": 849,
    "preview": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/QueueDispatcher.kt",
    "chars": 3016,
    "preview": "/*\n * Copyright (C) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/RecordedRequest.kt",
    "chars": 3296,
    "preview": "/*\n * Copyright (C) 2011 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/SocketEffect.kt",
    "chars": 1677,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/SocketHandler.kt",
    "chars": 940,
    "preview": "/*\n * Copyright (C) 2022 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/internal/BufferMockResponseBody.kt",
    "chars": 1142,
    "preview": "/*\n * Copyright (c) 2022 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/internal/MockWebServerSocket.kt",
    "chars": 3425,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/internal/RecordedRequestFactory.kt",
    "chars": 3380,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/internal/ThrottledSink.kt",
    "chars": 1566,
    "preview": "/*\n * Copyright (c) 2022 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/main/kotlin/mockwebserver3/internal/TriggerSink.kt",
    "chars": 1453,
    "preview": "/*\n * Copyright (c) 2022 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/test/java/mockwebserver3/CustomDispatcherTest.kt",
    "chars": 3274,
    "preview": "/*\n * Copyright (C) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/test/java/mockwebserver3/MockResponseSniTest.kt",
    "chars": 6417,
    "preview": "/*\n * Copyright (C) 2022 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/test/java/mockwebserver3/MockWebServerTest.kt",
    "chars": 28722,
    "preview": "/*\n * Copyright (C) 2011 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver/src/test/java/mockwebserver3/RecordedRequestTest.kt",
    "chars": 5444,
    "preview": "/*\n * Copyright (C) 2012 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver/src/test/java/mockwebserver3/internal/http2/Http2Server.kt",
    "chars": 6544,
    "preview": "/*\n * Copyright (C) 2011 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "mockwebserver-deprecated/api/mockwebserver.api",
    "chars": 10414,
    "preview": "public abstract class okhttp3/mockwebserver/Dispatcher {\n\tpublic fun <init> ()V\n\tpublic abstract fun dispatch (Lokhttp3/"
  },
  {
    "path": "mockwebserver-deprecated/build.gradle.kts",
    "chars": 523,
    "preview": "plugins {\n  kotlin(\"jvm\")\n  id(\"okhttp.publish-conventions\")\n  id(\"okhttp.jvm-conventions\")\n  id(\"okhttp.quality-convent"
  },
  {
    "path": "mockwebserver-deprecated/src/main/java9/module-info.java",
    "chars": 139,
    "preview": "@SuppressWarnings(\"module\")\nmodule okhttp3.mockwebserver {\n  requires okhttp3;\n  exports okhttp3.mockwebserver;\n  requir"
  },
  {
    "path": "mockwebserver-deprecated/src/main/kotlin/okhttp3/mockwebserver/DeprecationBridge.kt",
    "chars": 4422,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-deprecated/src/main/kotlin/okhttp3/mockwebserver/Dispatcher.kt",
    "chars": 894,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-deprecated/src/main/kotlin/okhttp3/mockwebserver/MockResponse.kt",
    "chars": 7264,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-deprecated/src/main/kotlin/okhttp3/mockwebserver/MockWebServer.kt",
    "chars": 4660,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-deprecated/src/main/kotlin/okhttp3/mockwebserver/PushPromise.kt",
    "chars": 1700,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-deprecated/src/main/kotlin/okhttp3/mockwebserver/QueueDispatcher.kt",
    "chars": 1344,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-deprecated/src/main/kotlin/okhttp3/mockwebserver/RecordedRequest.kt",
    "chars": 4217,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-deprecated/src/main/kotlin/okhttp3/mockwebserver/SocketPolicy.kt",
    "chars": 1073,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-deprecated/src/test/java/okhttp3/mockwebserver/KotlinSourceModernTest.kt",
    "chars": 7514,
    "preview": "/*\n * Copyright (C) 2019 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-deprecated/src/test/java/okhttp3/mockwebserver/MockWebServerTest.kt",
    "chars": 22818,
    "preview": "/*\n * Copyright (C) 2011 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "mockwebserver-junit4/README.md",
    "chars": 706,
    "preview": "MockWebServer for JUnit 4\n=========================\n\nThis module integrates mockwebserver3.MockWebServer with JUnit 4.\n\n"
  },
  {
    "path": "mockwebserver-junit4/api/mockwebserver3-junit4.api",
    "chars": 183,
    "preview": "public final class mockwebserver3/junit4/MockWebServerRule : org/junit/rules/ExternalResource {\n\tpublic fun <init> ()V\n\t"
  },
  {
    "path": "mockwebserver-junit4/build.gradle.kts",
    "chars": 389,
    "preview": "plugins {\n  kotlin(\"jvm\")\n  id(\"okhttp.publish-conventions\")\n  id(\"okhttp.jvm-conventions\")\n  id(\"okhttp.quality-convent"
  },
  {
    "path": "mockwebserver-junit4/src/main/java9/module-info.java",
    "chars": 139,
    "preview": "@SuppressWarnings(\"module\")\nmodule mockwebserver3.junit4 {\n  requires okhttp3;\n  exports mockwebserver3.junit4;\n  requir"
  },
  {
    "path": "mockwebserver-junit4/src/main/kotlin/mockwebserver3/junit4/MockWebServerRule.kt",
    "chars": 1454,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-junit4/src/test/java/mockwebserver3/junit4/MockWebServerRuleTest.kt",
    "chars": 1610,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-junit5/README.md",
    "chars": 665,
    "preview": "MockWebServer for JUnit 5\n=========================\n\nThis module integrates mockwebserver3.MockWebServer with JUnit 5.\n\n"
  },
  {
    "path": "mockwebserver-junit5/api/mockwebserver3-junit5.api",
    "chars": 114,
    "preview": "public abstract interface annotation class mockwebserver3/junit5/StartStop : java/lang/annotation/Annotation {\n}\n\n"
  },
  {
    "path": "mockwebserver-junit5/build.gradle.kts",
    "chars": 546,
    "preview": "plugins {\n  kotlin(\"jvm\")\n  id(\"okhttp.publish-conventions\")\n  id(\"okhttp.jvm-conventions\")\n  id(\"okhttp.quality-convent"
  },
  {
    "path": "mockwebserver-junit5/src/main/java9/module-info.java",
    "chars": 121,
    "preview": "@SuppressWarnings(\"module\")\nmodule mockwebserver3.junit5 {\n  requires okhttp3;\n  opens mockwebserver3.junit5.internal;\n}"
  },
  {
    "path": "mockwebserver-junit5/src/main/kotlin/mockwebserver3/junit5/StartStop.kt",
    "chars": 1283,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-junit5/src/main/kotlin/mockwebserver3/junit5/internal/StartStopExtension.kt",
    "chars": 2493,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "mockwebserver-junit5/src/test/java/mockwebserver3/junit5/StartStopTest.kt",
    "chars": 3342,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "module-tests/build.gradle.kts",
    "chars": 1855,
    "preview": "import okhttp3.buildsupport.testJavaVersion\n\nplugins {\n  id(\"okhttp.base-conventions\")\n  id(\"java\")\n  id(\"application\")\n"
  },
  {
    "path": "module-tests/src/main/java/module-info.java",
    "chars": 156,
    "preview": "@SuppressWarnings(\"module\")\nmodule okhttp3.modules {\n  requires okhttp3;\n  requires okhttp3.logging;\n  requires jdk.cryp"
  },
  {
    "path": "module-tests/src/main/java/okhttp3/modules/Main.java",
    "chars": 934,
    "preview": "/*\n * Copyright (C) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "module-tests/src/main/java/okhttp3/modules/OkHttpCaller.java",
    "chars": 1186,
    "preview": "/*\n * Copyright (C) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "module-tests/src/test/java/module-info.java",
    "chars": 317,
    "preview": "@SuppressWarnings(\"module\")\nmodule okhttp3.modules.test {\n  requires okhttp3;\n  requires okhttp3.logging;\n  requires moc"
  },
  {
    "path": "module-tests/src/test/java/okhttp3/modules/test/JavaModuleTest.java",
    "chars": 2201,
    "preview": "/*\n * Copyright (C) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "native-image-tests/README.md",
    "chars": 242,
    "preview": "Native Image Tests\n==================\n\nThis executes OkHttp's test suite inside a Graalvm image.\n\nExecute\n-------\n\nThe n"
  },
  {
    "path": "native-image-tests/build.gradle.kts",
    "chars": 1291,
    "preview": "import org.jetbrains.kotlin.gradle.dsl.JvmTarget\nimport org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nplugins {\n  id("
  },
  {
    "path": "native-image-tests/src/test/kotlin/okhttp3/nativeimage/PublicSuffixDatabaseTest.kt",
    "chars": 964,
    "preview": "/*\n * Copyright (C) 2022 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "native-image-tests/src/test/kotlin/okhttp3/nativeimage/SampleTest.kt",
    "chars": 1484,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "native-image-tests/src/test/kotlin/okhttp3/nativeimage/WithArgumentSourceTest.kt",
    "chars": 1632,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "native-image-tests/src/test/resources/META-INF/native-image/okhttp/nit/resource-config.json",
    "chars": 78,
    "preview": "{\n  \"resources\": [\n    {\"pattern\": \"web-platform-test-urltestdata.txt\"}\n  ]\n}\n"
  },
  {
    "path": "okcurl/README.md",
    "chars": 261,
    "preview": "OkCurl\n======\n\n_A curl for the next-generation web._\n\nOkCurl is an OkHttp-backed curl clone which allows you to test OkH"
  },
  {
    "path": "okcurl/build.gradle.kts",
    "chars": 2447,
    "preview": "import kotlinx.validation.ApiValidationExtension\nimport okhttp3.buildsupport.testJavaVersion\nimport org.graalvm.buildtoo"
  },
  {
    "path": "okcurl/okcurl",
    "chars": 83,
    "preview": "#!/bin/sh -e\n\n../gradlew -q --console plain nativeBuild\n\n./build/graal/okcurl \"$@\"\n"
  },
  {
    "path": "okcurl/src/main/kotlin/okhttp3/curl/Main.kt",
    "chars": 6184,
    "preview": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "okcurl/src/main/kotlin/okhttp3/curl/MainCommandLine.kt",
    "chars": 768,
    "preview": "/*\n * Copyright (C) 2022 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "okcurl/src/main/kotlin/okhttp3/curl/internal/-MainCommon.kt",
    "chars": 2753,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "okcurl/src/main/kotlin/okhttp3/curl/logging/LoggingUtil.kt",
    "chars": 2724,
    "preview": "/*\n * Copyright (C) 2022 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "okcurl/src/main/kotlin/okhttp3/curl/logging/MessageFormatter.kt",
    "chars": 845,
    "preview": "/*\n * Copyright (C) 2022 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "okcurl/src/main/kotlin/okhttp3/curl/logging/OneLineLogFormat.kt",
    "chars": 2101,
    "preview": "/*\n * Copyright (C) 2022 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "okcurl/src/main/resources/META-INF/native-image/okhttp3/okcurl/reflect-config.json",
    "chars": 4,
    "preview": "[\n]\n"
  },
  {
    "path": "okcurl/src/main/resources/META-INF/native-image/okhttp3/okcurl/resource-config.json",
    "chars": 70,
    "preview": "{\n  \"resources\": [\n    {\"pattern\": \"okcurl-version.properties\"}\n  ]\n}\n"
  },
  {
    "path": "okcurl/src/main/resources-templates/okcurl-version.properties",
    "chars": 26,
    "preview": "version=${projectVersion}\n"
  },
  {
    "path": "okcurl/src/test/kotlin/okhttp3/curl/MainTest.kt",
    "chars": 4429,
    "preview": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "okhttp/Module.md",
    "chars": 74,
    "preview": "# Module okhttp\n\nAn HTTP+HTTP/2 client for Android and Java applications.\n"
  },
  {
    "path": "okhttp/api/android/okhttp.api",
    "chars": 74072,
    "preview": "public final class okhttp3/Address {\n\tpublic final fun -deprecated_certificatePinner ()Lokhttp3/CertificatePinner;\n\tpubl"
  },
  {
    "path": "okhttp/api/jvm/okhttp.api",
    "chars": 74014,
    "preview": "public final class okhttp3/Address {\n\tpublic final fun -deprecated_certificatePinner ()Lokhttp3/CertificatePinner;\n\tpubl"
  },
  {
    "path": "okhttp/build.gradle.kts",
    "chars": 11644,
    "preview": "@file:Suppress(\"UnstableApiUsage\")\n\nimport okhttp3.buildsupport.alpnBootVersion\nimport okhttp3.buildsupport.platform\nimp"
  },
  {
    "path": "okhttp/okhttp3.pro",
    "chars": 512,
    "preview": "# JSR 305 annotations are for embedding nullability information.\n-dontwarn javax.annotation.**\n\n# Animal Sniffer compile"
  },
  {
    "path": "okhttp/src/androidHostTest/kotlin/okhttp3/internal/publicsuffix/PublicSuffixTesting.android.kt",
    "chars": 974,
    "preview": "/*\n * Copyright (C) 2024 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "okhttp/src/androidHostTest/resources/okhttp3/robolectric.properties",
    "chars": 47,
    "preview": "# Robolectric on API 36 requires JDK 21\nsdk=35\n"
  },
  {
    "path": "okhttp/src/androidMain/AndroidManifest.xml",
    "chars": 604,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:tools=\"http://schemas.android.com/tools\"\n    "
  },
  {
    "path": "okhttp/src/androidMain/baseline-prof.txt",
    "chars": 130998,
    "preview": "HSPLandroidx/arch/core/executor/ArchTaskExecutor;-><init>()V\nHSPLandroidx/arch/core/executor/ArchTaskExecutor;->getInsta"
  },
  {
    "path": "okhttp/src/androidMain/kotlin/okhttp3/OkHttp.android.kt",
    "chars": 1382,
    "preview": "/*\n * Copyright (C) 2025 Block, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "okhttp/src/androidMain/kotlin/okhttp3/internal/platform/Android10Platform.kt",
    "chars": 4562,
    "preview": "/*\n * Copyright (C) 2016 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  }
]

// ... and 583 more files (download for full content)

About this extraction

This page contains the full source code of the square/okhttp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 783 files (5.7 MB), approximately 1.5M tokens, and a symbol index with 327 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!