Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ public class OkHttpEngine(override val config: OkHttpConfig) : HttpClientEngineB
private fun createOkHttpClient(timeoutExtension: HttpTimeoutConfig?): OkHttpClient {
val builder = (config.preconfigured ?: okHttpClientPrototype).newBuilder()

builder.dispatcher(Dispatcher())
if (config.preconfigured == null) {
builder.dispatcher(Dispatcher())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably we should just drop this line as OkHttp already creates Dispatcher by default:

internal var dispatcher: Dispatcher = Dispatcher()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably we should just drop this line as OkHttp already creates Dispatcher by default:

internal var dispatcher: Dispatcher = Dispatcher()

Yes, because even when copying okHttpClientPrototype, Dispatcher should be shared, as stated in the docs:

OkHttp performs best when you create a single OkHttpClient instance and reuse it for all of your HTTP calls. This is because each client holds its own connection pool and thread pools. Reusing connections and threads reduces latency and saves memory. Conversely, creating a client for each request wastes resources on idle pools.

The above should apply to prototype client also, new Dispatcher should NEVER be set.

}
builder.apply(config.config)
config.proxy?.let { builder.proxy(it) }
timeoutExtension?.let {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2014-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.client.engine.okhttp

import okhttp3.Dispatcher
import okhttp3.OkHttpClient
import kotlin.test.Test
import kotlin.test.assertSame

class OkHttpEngineTest {

@Test
fun usesPreconfiguredDispatcher() {
val dispatcher = Dispatcher()
val preconfiguredClient = OkHttpClient.Builder()
.dispatcher(dispatcher)
.build()

val engine = OkHttpEngine(OkHttpConfig().apply { preconfigured = preconfiguredClient })
val cacheField = engine.javaClass.getDeclaredField("clientCache").apply { isAccessible = true }
val clientCache = cacheField.get(engine) as Map<*, *>

val client = clientCache[null] as OkHttpClient

assertSame(dispatcher, client.dispatcher)
}
}