Skip to content

Commit cbf98f7

Browse files
authored
feat: OkHttp4Engine (#1150)
1 parent be6b82d commit cbf98f7

File tree

19 files changed

+454
-51
lines changed

19 files changed

+454
-51
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": "7acc674e-0dfe-461a-a5c3-f946e14a3ec7",
3+
"type": "feature",
4+
"description": "Add OkHttp4Engine, an HTTP engine which uses okhttp3:4.x"
5+
}

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ aws-kotlin-repo-tools-version = "0.4.10"
88
coroutines-version = "1.8.1"
99
atomicfu-version = "0.24.0"
1010
okhttp-version = "5.0.0-alpha.14"
11+
okhttp4-version = "4.12.0"
1112
okio-version = "3.9.0"
1213
otel-version = "1.32.0"
1314
slf4j-version = "2.0.9"
@@ -51,6 +52,7 @@ kotlinx-coroutines-slf4j = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-
5152

5253
okio = { module = "com.squareup.okio:okio", version.ref = "okio-version" }
5354
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp-version" }
55+
okhttp4 = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp4-version" }
5456
okhttp-coroutines = { module = "com.squareup.okhttp3:okhttp-coroutines", version.ref = "okhttp-version" }
5557
opentelemetry-api = { module = "io.opentelemetry:opentelemetry-api", version.ref = "otel-version" }
5658
opentelemetry-sdk-testing = {module = "io.opentelemetry:opentelemetry-sdk-testing", version.ref = "otel-version" }

runtime/protocol/http-client-engines/http-client-engine-okhttp/api/http-client-engine-okhttp.api

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,54 @@
1+
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/HttpEngineEventListener : okhttp3/EventListener {
2+
public fun <init> (Lokhttp3/ConnectionPool;Laws/smithy/kotlin/runtime/net/HostResolver;Lokhttp3/Dispatcher;Laws/smithy/kotlin/runtime/http/engine/internal/HttpClientMetrics;Lokhttp3/Call;)V
3+
public fun cacheConditionalHit (Lokhttp3/Call;Lokhttp3/Response;)V
4+
public fun cacheHit (Lokhttp3/Call;Lokhttp3/Response;)V
5+
public fun cacheMiss (Lokhttp3/Call;)V
6+
public fun callEnd (Lokhttp3/Call;)V
7+
public fun callFailed (Lokhttp3/Call;Ljava/io/IOException;)V
8+
public fun callStart (Lokhttp3/Call;)V
9+
public fun canceled (Lokhttp3/Call;)V
10+
public fun connectEnd (Lokhttp3/Call;Ljava/net/InetSocketAddress;Ljava/net/Proxy;Lokhttp3/Protocol;)V
11+
public fun connectFailed (Lokhttp3/Call;Ljava/net/InetSocketAddress;Ljava/net/Proxy;Lokhttp3/Protocol;Ljava/io/IOException;)V
12+
public fun connectStart (Lokhttp3/Call;Ljava/net/InetSocketAddress;Ljava/net/Proxy;)V
13+
public fun connectionAcquired (Lokhttp3/Call;Lokhttp3/Connection;)V
14+
public fun connectionReleased (Lokhttp3/Call;Lokhttp3/Connection;)V
15+
public fun dnsEnd (Lokhttp3/Call;Ljava/lang/String;Ljava/util/List;)V
16+
public fun dnsStart (Lokhttp3/Call;Ljava/lang/String;)V
17+
public fun proxySelectEnd (Lokhttp3/Call;Lokhttp3/HttpUrl;Ljava/util/List;)V
18+
public fun proxySelectStart (Lokhttp3/Call;Lokhttp3/HttpUrl;)V
19+
public fun requestBodyEnd (Lokhttp3/Call;J)V
20+
public fun requestBodyStart (Lokhttp3/Call;)V
21+
public fun requestFailed (Lokhttp3/Call;Ljava/io/IOException;)V
22+
public fun requestHeadersEnd (Lokhttp3/Call;Lokhttp3/Request;)V
23+
public fun requestHeadersStart (Lokhttp3/Call;)V
24+
public fun responseBodyEnd (Lokhttp3/Call;J)V
25+
public fun responseBodyStart (Lokhttp3/Call;)V
26+
public fun responseFailed (Lokhttp3/Call;Ljava/io/IOException;)V
27+
public fun responseHeadersEnd (Lokhttp3/Call;Lokhttp3/Response;)V
28+
public fun responseHeadersStart (Lokhttp3/Call;)V
29+
public fun satisfactionFailure (Lokhttp3/Call;Lokhttp3/Response;)V
30+
public fun secureConnectEnd (Lokhttp3/Call;Lokhttp3/Handshake;)V
31+
public fun secureConnectStart (Lokhttp3/Call;)V
32+
}
33+
34+
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/MetricsInterceptor : okhttp3/Interceptor {
35+
public static final field INSTANCE Laws/smithy/kotlin/runtime/http/engine/okhttp/MetricsInterceptor;
36+
public fun intercept (Lokhttp3/Interceptor$Chain;)Lokhttp3/Response;
37+
}
38+
39+
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpCall : aws/smithy/kotlin/runtime/http/HttpCall {
40+
public fun <init> (Laws/smithy/kotlin/runtime/http/request/HttpRequest;Laws/smithy/kotlin/runtime/http/response/HttpResponse;Laws/smithy/kotlin/runtime/time/Instant;Laws/smithy/kotlin/runtime/time/Instant;Lkotlin/coroutines/CoroutineContext;Lokhttp3/Call;)V
41+
public synthetic fun <init> (Laws/smithy/kotlin/runtime/http/request/HttpRequest;Laws/smithy/kotlin/runtime/http/response/HttpResponse;Laws/smithy/kotlin/runtime/time/Instant;Laws/smithy/kotlin/runtime/time/Instant;Lkotlin/coroutines/CoroutineContext;Lokhttp3/Call;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
42+
public fun cancelInFlight ()V
43+
public fun copy (Laws/smithy/kotlin/runtime/http/request/HttpRequest;Laws/smithy/kotlin/runtime/http/response/HttpResponse;)Laws/smithy/kotlin/runtime/http/HttpCall;
44+
public final fun getCall ()Lokhttp3/Call;
45+
}
46+
47+
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpDns : okhttp3/Dns {
48+
public fun <init> (Laws/smithy/kotlin/runtime/net/HostResolver;)V
49+
public fun lookup (Ljava/lang/String;)Ljava/util/List;
50+
}
51+
152
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpEngine : aws/smithy/kotlin/runtime/http/engine/HttpClientEngineBase {
253
public static final field Companion Laws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpEngine$Companion;
354
public fun <init> ()V
@@ -32,3 +83,51 @@ public final class aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpEngineConf
3283
public final fun invoke (Lkotlin/jvm/functions/Function1;)Laws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpEngineConfig;
3384
}
3485

86+
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpEngineKt {
87+
public static final fun buildClient (Laws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpEngineConfig;Laws/smithy/kotlin/runtime/http/engine/internal/HttpClientMetrics;)Lokhttp3/OkHttpClient;
88+
}
89+
90+
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpHeadersAdapter : aws/smithy/kotlin/runtime/http/Headers {
91+
public fun <init> (Lokhttp3/Headers;)V
92+
public fun contains (Ljava/lang/String;)Z
93+
public synthetic fun contains (Ljava/lang/String;Ljava/lang/Object;)Z
94+
public fun contains (Ljava/lang/String;Ljava/lang/String;)Z
95+
public fun entries ()Ljava/util/Set;
96+
public fun forEach (Lkotlin/jvm/functions/Function2;)V
97+
public synthetic fun get (Ljava/lang/String;)Ljava/lang/Object;
98+
public fun get (Ljava/lang/String;)Ljava/lang/String;
99+
public fun getAll (Ljava/lang/String;)Ljava/util/List;
100+
public fun getCaseInsensitiveName ()Z
101+
public fun isEmpty ()Z
102+
public fun names ()Ljava/util/Set;
103+
}
104+
105+
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpProxyAuthenticator : okhttp3/Authenticator {
106+
public fun <init> (Laws/smithy/kotlin/runtime/http/engine/ProxySelector;)V
107+
public fun authenticate (Lokhttp3/Route;Lokhttp3/Response;)Lokhttp3/Request;
108+
}
109+
110+
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpProxySelector : java/net/ProxySelector {
111+
public fun <init> (Laws/smithy/kotlin/runtime/http/engine/ProxySelector;)V
112+
public fun connectFailed (Ljava/net/URI;Ljava/net/SocketAddress;Ljava/io/IOException;)V
113+
public fun select (Ljava/net/URI;)Ljava/util/List;
114+
}
115+
116+
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpUtilsKt {
117+
public static final fun errCode (Ljava/lang/Exception;)Laws/smithy/kotlin/runtime/http/HttpErrorCode;
118+
public static final fun mapOkHttpExceptions (Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;
119+
public static final fun toOkHttpHeaders (Laws/smithy/kotlin/runtime/http/Headers;)Lokhttp3/Headers;
120+
public static final fun toOkHttpRequest (Laws/smithy/kotlin/runtime/http/request/HttpRequest;Laws/smithy/kotlin/runtime/operation/ExecutionContext;Lkotlin/coroutines/CoroutineContext;Laws/smithy/kotlin/runtime/http/engine/internal/HttpClientMetrics;)Lokhttp3/Request;
121+
public static final fun toSdkResponse (Lokhttp3/Response;)Laws/smithy/kotlin/runtime/http/response/HttpResponse;
122+
public static final fun toUrl (Ljava/net/URI;)Laws/smithy/kotlin/runtime/net/url/Url;
123+
}
124+
125+
public final class aws/smithy/kotlin/runtime/http/engine/okhttp/StreamingRequestBody : okhttp3/RequestBody {
126+
public fun <init> (Laws/smithy/kotlin/runtime/http/HttpBody;Lkotlin/coroutines/CoroutineContext;)V
127+
public fun contentLength ()J
128+
public fun contentType ()Lokhttp3/MediaType;
129+
public fun isDuplex ()Z
130+
public fun isOneShot ()Z
131+
public fun writeTo (Lokio/BufferedSink;)V
132+
}
133+

runtime/protocol/http-client-engines/http-client-engine-okhttp/jvm/src/aws/smithy/kotlin/runtime/http/engine/okhttp/HttpEngineEventListener.kt

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package aws.smithy.kotlin.runtime.http.engine.okhttp
66

77
import aws.smithy.kotlin.runtime.ExperimentalApi
8+
import aws.smithy.kotlin.runtime.InternalApi
89
import aws.smithy.kotlin.runtime.http.engine.EngineAttributes
910
import aws.smithy.kotlin.runtime.http.engine.internal.HttpClientMetrics
1011
import aws.smithy.kotlin.runtime.net.HostResolver
@@ -31,19 +32,20 @@ internal const val TELEMETRY_SCOPE = "aws.smithy.kotlin.runtime.http.engine.okht
3132

3233
// see https://square.github.io/okhttp/features/events/#eventlistener for example callback flow
3334
@OptIn(ExperimentalApi::class)
34-
internal class HttpEngineEventListener(
35+
@InternalApi
36+
public class HttpEngineEventListener(
3537
private val pool: ConnectionPool,
3638
private val hr: HostResolver,
3739
private val dispatcher: Dispatcher,
3840
private val metrics: HttpClientMetrics,
3941
call: Call,
4042
) : EventListener() {
41-
private val provider: TelemetryProvider = call.request().tag<SdkRequestTag>()?.callContext?.telemetryProvider ?: TelemetryProvider.None
43+
private val provider: TelemetryProvider = call.request().tag(SdkRequestTag::class.java)?.callContext?.telemetryProvider ?: TelemetryProvider.None
4244
private val traceSpan = provider.tracerProvider
4345
.getOrCreateTracer(TELEMETRY_SCOPE)
4446
.createSpan("HTTP")
4547

46-
private val logger = call.request().tag<SdkRequestTag>()?.callContext?.logger<OkHttpEngine>() ?: LoggerProvider.None.getLogger<OkHttpEngine>()
48+
private val logger = call.request().tag(SdkRequestTag::class.java)?.callContext?.logger<OkHttpEngine>() ?: LoggerProvider.None.getLogger<OkHttpEngine>()
4749

4850
// callStart() is invoked immediately when enqueued, next success phase is either dnsStart() or connectionAcquired()
4951
// see https://github.com/square/okhttp/blob/7c92ed0879477eddb2fce6b4066d151525d5687f/okhttp/src/jvmMain/kotlin/okhttp3/internal/connection/RealCall.kt#L167-L175
@@ -84,22 +86,22 @@ internal class HttpEngineEventListener(
8486
trace { "dns query: domain=$domainName" }
8587
}
8688

87-
override fun dnsEnd(call: Call, domainName: String, inetAddressList: List<InetAddress>) =
89+
override fun dnsEnd(call: Call, domainName: String, inetAddressList: List<InetAddress>): Unit =
8890
trace { "dns resolved: domain=$domainName; records=$inetAddressList" }
8991

90-
override fun proxySelectStart(call: Call, url: HttpUrl) = trace { "proxy select start: url=$url" }
92+
override fun proxySelectStart(call: Call, url: HttpUrl): Unit = trace { "proxy select start: url=$url" }
9193

92-
override fun proxySelectEnd(call: Call, url: HttpUrl, proxies: List<Proxy>) =
94+
override fun proxySelectEnd(call: Call, url: HttpUrl, proxies: List<Proxy>): Unit =
9395
trace { "proxy select end: url=$url; proxies=$proxies" }
9496

95-
override fun connectStart(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy) =
97+
override fun connectStart(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy): Unit =
9698
trace { "starting connection: addr=$inetSocketAddress; proxy=$proxy" }
9799

98-
override fun secureConnectStart(call: Call) = trace { "initiating TLS connection" }
100+
override fun secureConnectStart(call: Call): Unit = trace { "initiating TLS connection" }
99101

100-
override fun secureConnectEnd(call: Call, handshake: Handshake?) = trace { "TLS connect end: handshake=$handshake" }
102+
override fun secureConnectEnd(call: Call, handshake: Handshake?): Unit = trace { "TLS connect end: handshake=$handshake" }
101103

102-
override fun connectEnd(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy, protocol: Protocol?) =
104+
override fun connectEnd(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy, protocol: Protocol?): Unit =
103105
trace { "connection established: addr=$inetSocketAddress; proxy=$proxy; protocol=$protocol" }
104106

105107
override fun connectFailed(
@@ -139,7 +141,7 @@ internal class HttpEngineEventListener(
139141
trace { "connection acquired: conn(id=$connId)=$connection; connPool: total=${pool.connectionCount()}, idle=${pool.idleConnectionCount()}" }
140142
}
141143

142-
override fun requestHeadersStart(call: Call) = trace { "sending request headers" }
144+
override fun requestHeadersStart(call: Call): Unit = trace { "sending request headers" }
143145

144146
override fun requestHeadersEnd(call: Call, request: Request) {
145147
if (request.body == null) {
@@ -149,34 +151,34 @@ internal class HttpEngineEventListener(
149151
trace { "finished sending request headers" }
150152
}
151153

152-
override fun requestBodyStart(call: Call) = trace { "sending request body" }
154+
override fun requestBodyStart(call: Call): Unit = trace { "sending request body" }
153155

154156
override fun requestBodyEnd(call: Call, byteCount: Long) {
155157
requestTimeEnd = TimeSource.Monotonic.markNow()
156158
trace { "finished sending request body: bytesSent=$byteCount" }
157159
}
158160

159-
override fun requestFailed(call: Call, ioe: IOException) = trace(ioe) { "request failed" }
161+
override fun requestFailed(call: Call, ioe: IOException): Unit = trace(ioe) { "request failed" }
160162

161163
override fun responseHeadersStart(call: Call) {
162164
requestTimeEnd?.elapsedNow()?.let { ttfb ->
163165
metrics.timeToFirstByteDuration.recordSeconds(ttfb)
164-
call.request().tag<SdkRequestTag>()?.execContext?.set(EngineAttributes.TimeToFirstByte, ttfb)
166+
call.request().tag(SdkRequestTag::class.java)?.execContext?.set(EngineAttributes.TimeToFirstByte, ttfb)
165167
}
166168
trace { "response headers start" }
167169
}
168170

169171
override fun responseHeadersEnd(call: Call, response: Response) {
170-
val contentLength = response.body.contentLength()
172+
val contentLength = response.body?.contentLength()
171173
trace { "response headers end: contentLengthHeader=$contentLength" }
172174
}
173175

174-
override fun responseBodyStart(call: Call) = trace { "response body available" }
176+
override fun responseBodyStart(call: Call): Unit = trace { "response body available" }
175177

176-
override fun responseBodyEnd(call: Call, byteCount: Long) =
178+
override fun responseBodyEnd(call: Call, byteCount: Long): Unit =
177179
trace { "response body finished: bytesConsumed=$byteCount" }
178180

179-
override fun responseFailed(call: Call, ioe: IOException) = trace(ioe) { "response failed" }
181+
override fun responseFailed(call: Call, ioe: IOException): Unit = trace(ioe) { "response failed" }
180182

181183
override fun connectionReleased(call: Call, connection: Connection) {
182184
metrics.acquiredConnections = pool.connectionCount().toLong()
@@ -201,16 +203,16 @@ internal class HttpEngineEventListener(
201203
traceSpan.close()
202204
}
203205

204-
override fun canceled(call: Call) = trace { "call cancelled" }
206+
override fun canceled(call: Call): Unit = trace { "call cancelled" }
205207

206208
// NOTE: we don't configure a cache and should never get the rest of these events,
207209
// seeing these messages logged means we configured something wrong
208210

209-
override fun satisfactionFailure(call: Call, response: Response) = trace { "cache satisfaction failure" }
211+
override fun satisfactionFailure(call: Call, response: Response): Unit = trace { "cache satisfaction failure" }
210212

211-
override fun cacheConditionalHit(call: Call, cachedResponse: Response) = trace { "cache conditional hit" }
213+
override fun cacheConditionalHit(call: Call, cachedResponse: Response): Unit = trace { "cache conditional hit" }
212214

213-
override fun cacheHit(call: Call, response: Response) = trace { "cache hit" }
215+
override fun cacheHit(call: Call, response: Response): Unit = trace { "cache hit" }
214216

215-
override fun cacheMiss(call: Call) = trace { "cache miss" }
217+
override fun cacheMiss(call: Call): Unit = trace { "cache miss" }
216218
}

runtime/protocol/http-client-engines/http-client-engine-okhttp/jvm/src/aws/smithy/kotlin/runtime/http/engine/okhttp/MetricsInterceptor.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package aws.smithy.kotlin.runtime.http.engine.okhttp
66

7+
import aws.smithy.kotlin.runtime.InternalApi
78
import aws.smithy.kotlin.runtime.collections.Attributes
89
import aws.smithy.kotlin.runtime.collections.attributesOf
910
import aws.smithy.kotlin.runtime.telemetry.metrics.MonotonicCounter
@@ -13,10 +14,11 @@ import okio.*
1314
/**
1415
* Instrument the HTTP throughput metrics (e.g. bytes rcvd/sent)
1516
*/
16-
internal object MetricsInterceptor : Interceptor {
17+
@InternalApi
18+
public object MetricsInterceptor : Interceptor {
1719
override fun intercept(chain: Interceptor.Chain): Response {
1820
val originalRequest = chain.request()
19-
val metrics = originalRequest.tag<SdkRequestTag>()?.metrics ?: return chain.proceed(originalRequest)
21+
val metrics = originalRequest.tag(SdkRequestTag::class.java)?.metrics ?: return chain.proceed(originalRequest)
2022

2123
val attrs = attributesOf { "server.address" to "${originalRequest.url.host}:${originalRequest.url.port}" }
2224
val request = if (originalRequest.body != null) {
@@ -28,12 +30,12 @@ internal object MetricsInterceptor : Interceptor {
2830
}
2931

3032
val originalResponse = chain.proceed(request)
31-
val response = if (originalResponse.body.contentLength() != 0L) {
33+
val response = if (originalResponse.body == null || originalResponse.body?.contentLength() == 0L) {
34+
originalResponse
35+
} else {
3236
originalResponse.newBuilder()
3337
.body(originalResponse.body.instrument(metrics.bytesReceived, attrs))
3438
.build()
35-
} else {
36-
originalResponse
3739
}
3840

3941
return response

runtime/protocol/http-client-engines/http-client-engine-okhttp/jvm/src/aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpEngine.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package aws.smithy.kotlin.runtime.http.engine.okhttp
77

8+
import aws.smithy.kotlin.runtime.InternalApi
89
import aws.smithy.kotlin.runtime.http.HttpCall
910
import aws.smithy.kotlin.runtime.http.config.EngineFactory
1011
import aws.smithy.kotlin.runtime.http.engine.*
@@ -64,7 +65,7 @@ public class OkHttpEngine(
6465
// else). In both cases we need to ensure that the engine-side resources are cleaned up completely
6566
// since they wouldn't otherwise be. https://github.com/smithy-lang/smithy-kotlin/issues/1061
6667
if (cause != null) call.cancelInFlight()
67-
engineResponse.body.close()
68+
engineResponse.body?.close()
6869
}
6970
}
7071
}
@@ -79,7 +80,8 @@ public class OkHttpEngine(
7980
/**
8081
* Convert SDK version of HTTP configuration to OkHttp specific configuration and return the configured client
8182
*/
82-
private fun OkHttpEngineConfig.buildClient(metrics: HttpClientMetrics): OkHttpClient {
83+
@InternalApi
84+
public fun OkHttpEngineConfig.buildClient(metrics: HttpClientMetrics): OkHttpClient {
8385
val config = this
8486

8587
return OkHttpClient.Builder().apply {

runtime/protocol/http-client-engines/http-client-engine-okhttp/jvm/src/aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpHeadersAdapter.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55

66
package aws.smithy.kotlin.runtime.http.engine.okhttp
77

8+
import aws.smithy.kotlin.runtime.InternalApi
89
import aws.smithy.kotlin.runtime.http.Headers as SdkHeaders
910
import okhttp3.Headers as OkHttpHeaders
1011

1112
/**
1213
* Proxy [okhttp3.Headers] as [aws.smithy.kotlin.runtime.http.Headers]
1314
*/
14-
internal class OkHttpHeadersAdapter(private val headers: OkHttpHeaders) : SdkHeaders {
15+
@InternalApi
16+
public class OkHttpHeadersAdapter(private val headers: OkHttpHeaders) : SdkHeaders {
1517
override val caseInsensitiveName: Boolean = true
1618

1719
override fun getAll(name: String): List<String>? =

0 commit comments

Comments
 (0)