* Retry at most once when ECH fails
Also write some new ECH retry tests.
Also enforce restrictions on public_name structure.
Also rename EchRetryConfig to EchRetryPlan.
* Track behavior change
* Fold EchAwareDns into AndroidDns
I don't think each DNS feature should be its own DNS class; instead the single
DNS implementation should be configurable.
None of these classes have shipped in a stable release, so there's no risk
of breaking backwards-compatibility.
* Track changes in EchClientTest
* Completely fake out TLS for testing
This covers the happy path of OkHttp + MockWebServer with HTTPS.
This doesn't actually perform anything cryptographic; certificates
and protocols and things are transmitted in-memory rather than
over the wire.
This replaces the Okio.inMemorySocketPair() after the fake
TLS handshake; that way there's no risk of data leaking from
the pre-encrypted session to the post-encrypted session.
The useful capability this unlocks is testing TLS scenarios
like ECH retries, before we have a server-side TLS stack that
can support them.
* Important documentation
* Tests for the new APIs
* Make cancelation more robust
* Spotless
* Add overdue tests for FakeNetwork
The test that uses real OkHttp is good to confirm it works, but it
isn't useful for debugging problems with FakeNetwork.
* Fix flakiness with socket closing
* Completely fake out the network for simple tests
This covers the happy path of OkHttp + MockWebServer with no
TLS.
There's nothing too exciting here, other than using Okio's
inMemorySocketPair instead of a proper TCP socket for data.
In a follow-up PR I intend to layer on TLS including all the
exotic options like ECH and handshake failures. I won't do
any actual cryptography, just like how this doesn't do any
actual TCP packets.
* Update okhttp-testing-support/src/main/kotlin/okhttp3/sockets/FakeNetwork.kt
Co-authored-by: Yuri Schimke <yuri@schimke.ee>
* Spotless
* Track some API changes in Android tests
---------
Co-authored-by: Yuri Schimke <yuri@schimke.ee>
* Rearrange new DNS classes without changing behavior
Transport is now DnsQuery.Factory
CachingTransport is now DnsCache
StateMachineDnsCall.Query is now DnsQuery
This is intended to make it possible to have end-users get a DnsCache
instance without being exposed to the implementation details of our
transports and things.
* Use has-a, not is-a for the MemoryCache
* Update AndroidDns
* Track a test API change
* spotless
* Switch to Question as the Transport argument
It makes caching easier.
* New CachingTransport
* spotless
* Switch to ComparableTimeSource
* Switch from computeIfAbsent to putIfAbsent
The former isn't available on API 21.
* Add a tester just for the DnsCallStateMachine
A very nice perk of extracting it out so it could be reused for Android,
is that it's also a lot easier to test.
* Spotless
* Start including ECH data in RouteSelector results
This changes RouteSelector to use our new async API, when it is
available.
* Extract the execute() function
* Fixup Https results to use targetName
* Fixup some tests
* Use LinkedBlockingQueue instead of CompletableFuture
CompletableFuture isn't available until Android API 24
* Add ECH service metadata to Route.
Also combine DnsOverHttpsServer with FakeDns, so we can serve metadata
anywhere we're testing DNS.
Also move stuff to the 'internal' package in okhttp-dnsoverhttps, so we
can make symbols visible to the main okhttp module's tests.
* Fixup tests
* Test DNS returning zero results
Allow OkHttpClient overrides in Interceptor, generally anything settable on OkHttpClient.Builder can be overridden in application interceptor.
Tests that the effect of overrides takes effect and can be reversed.
* Call.addEventListener
Use this to install listeners after-the-fact, such as
in Interceptors or other EventListeners.
* apiDump
* Make eventListener updates atomic
* Fix
The first half is EventListenerAdapter, which mechanically
converts event function calls and emits event objects.
The second half is EventRecorder, which validates that the
right events are published.
This is in preparation for a follow-up where I intend
to dynamically add EventListeners to a Call.
Co-authored-by: Jesse Wilson <jwilson@squareup.com>
* Run all the tests in CI
We haven't been. I would have expected ./gradlew test
to run everything, but it doesn't. We need to explicitly
run jvmTest to get all of our tests to run.
* Use allTests, not jvmTest
* Support Corretto on osx-aarch_64
* Handle the exception message from OpenJDK 21
* Fixup Loom tests
---------
Co-authored-by: Jesse Wilson <jwilson@squareup.com>
Originally I was planning on implementing tags on
Request only, but that design broke as soon as any
interceptor used Request.newBuilder() to create a
copy of the Request - the instance that received the
tags might not be the instance that needed them.
Instead I'm introducing this behavior on the Call
object, which behaves less like a value. I expect
that users' expected lifetimes of tags will work
naturally this way.
It is an API hazard that we have tags on both
Requests and Calls. Perhaps if given the opportunity
to do it over, I'd omit support for tags on Requests.
Co-authored-by: Jesse Wilson <jwilson@squareup.com>
There's only one implementation in use, and so I'm
inlining it to call through what it ultimately does.
My motivation is to avoid retaining a reference to an
EventListener anywhere, because that value is going
from immutable to mutable.
Co-authored-by: Jesse Wilson <jwilson@squareup.com>
It's currently unused.
I'd like to bring this feature back soon, but using
regular Calls to make it happen rather than having
Connections created without a Call object. That should
avoid some special cases.
Co-authored-by: Jesse Wilson <jwilson@squareup.com>
So event listeners can see how long calls are waiting for
resources to become available.
This is the API only. I'll do the implementation in
follow-up.
Also note that I'm going to try my best to implement
this event pair to only fire for calls that actually
spend time in the queue. Calls that are immediately
promoted out of the queue should not get events.
* New BufferedSocket class
I'm starting to push Okio's socket throughout OkHttp,
and it turns out what I usually want is a BufferedSocket
instead.
* Flush not emit
* Track exception messages
* Use flush more
* Give the CountDownLatch something to count
* Fix typo
* Connection Upgrade for HTTP1 status code 101
See https://datatracker.ietf.org/doc/html/rfc9110#name-101-switching-protocols
* use socket.asOkioSocket()
* add socket to api
* remove the specific check on tcp connection upgrades
* create a dedicated HttpUpgradesTest
* chore
* add more test cases
* spotlessApply
* Use more MockWebServer features in tests
* Forbid HTTP/2
* Hook into Exchange for connection pool management
* Test events on successful upgrade
* Release the request body after an upgrade fails
* Upgrades don't promise a response body
* SpotlessApply
---------
Co-authored-by: Jesse Wilson <jwilson@squareup.com>
Also remove @ExperimentalOkHttpApi in a few places.
Also rename 'shutdown' to 'close' in MockWebServer
and Dispatcher.
Also rename QueueDispatcher.enqueueResponse() to
QueueDispatcher.enqueue.
Co-authored-by: Jesse Wilson <jwilson@squareup.com>
I'd like to update the API to improve observability into things
like ConnecitonPool, RoutePlanner, ConnectPlan, and ReusePlan.
And also into HTTP/2 internals like flow-control.
As-is this is more coupled to Call lifecycles and is somewhat
duplicative with ConnectionPool.
We'll do that work and make it a new public API, but we won't
have it in the public API at all for the 5.0 release.
Co-authored-by: Jesse Wilson <jwilson@squareup.com>
The Dispatcher class is an outlier here as it cannot implement
the Lockable interface without that leaking into its public API.
We do without in that case.
Co-authored-by: Jesse Wilson <jwilson@squareup.com>
* Change the locking mechanism to 'synchronized'
We migrated to ReentrantReadWriteLock to better support Loom,
but now we can use synchronized and still support Loom.
This old mechanism may be faster than ReentrantReadWriteLock.
* Update okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/concurrent/Lockable.kt
Co-authored-by: Yuri Schimke <yuri@schimke.ee>
---------
Co-authored-by: Jesse Wilson <jesse@swank.ca>
Co-authored-by: Yuri Schimke <yuri@schimke.ee>
* Split EventListener.retryDecision into retryDecision and followUpDecision
retryDecision has an exception, and is related to
connectivity failures.
followUpDecision has an intermediate response, and is
related to redirects and auth challenges.
This drops the reason strings, which have 'logging brain'
and I want to push our users towards 'metrics brain'.
* Spotless
* apiDump
* Fix another test
---------
Co-authored-by: Jesse Wilson <jwilson@squareup.com>
* Add retryDecision event to track retry logic in EventListener
Introduced a new `retryDecision` event to improve observability of retry logic. This includes detailed reasons for retry decisions, enhancing debugging. Updated relevant tests, interceptors, and event handling to accommodate the new event.
It also cleanly signals the boundary before a prior request and the follow up.
Refactor: Centralize lock management
This change centralizes the management of locks and conditions by introducing a centralised Locks registry. This allows for easier debugging and potential future improvements to lock usage.
The `withLock` and `newLockCondition` functions are now invoked through the `Locks` object, providing a central point of access.
We've got a race where we'll start a thread when we need
one, even if we've already started a thread. This changes
TaskRunner's behavior to never add a thread if we're
still waiting for a recently-added one to start running.
This is intended to reduce the number of threads contenting
for the TaskRunner lock as reported in this issue:
https://github.com/square/okhttp/issues/8388