Skip to content

Commit 982781a

Browse files
committed
chore: http client refactorings
1 parent 01f0f29 commit 982781a

File tree

5 files changed

+97
-85
lines changed

5 files changed

+97
-85
lines changed

shared/src/commonMain/kotlin/dev/suresh/http/HttpClient.kt

Lines changed: 86 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ val json by lazy {
3636
}
3737
}
3838

39+
typealias HttpClientConfigurer = HttpClientConfig<*>.() -> Unit
40+
3941
/**
4042
* Multiplatform HTTP client engine configuration
4143
*
@@ -46,85 +48,89 @@ expect fun httpClient(
4648
timeout: Timeout = Timeout.DEFAULT,
4749
retry: Retry = Retry.DEFAULT,
4850
kLogger: KLogger = log,
49-
config: HttpClientConfig<*>.() -> Unit = {
50-
install(Resources)
51-
52-
install(ContentNegotiation) { json(json) }
53-
54-
install(ContentEncoding) {
55-
deflate(1.0F)
56-
gzip(0.9F)
57-
}
58-
59-
install(HttpRequestRetry) {
60-
maxRetries = retry.attempts
61-
retryOnException(retryOnTimeout = true)
62-
retryOnServerErrors()
63-
exponentialDelay(maxDelayMs = retry.maxDelay.inWholeMilliseconds)
64-
// modifyRequest { it.headers.append("X_RETRY_COUNT", retryCount.toString()) }
65-
}
66-
67-
install(HttpTimeout) {
68-
connectTimeoutMillis = timeout.connection.inWholeMilliseconds
69-
requestTimeoutMillis = timeout.read.inWholeMilliseconds
70-
socketTimeoutMillis = timeout.write.inWholeMilliseconds
71-
}
72-
73-
install(HttpCookies)
74-
75-
install(Logging) {
76-
level =
77-
when {
78-
kLogger.isDebugEnabled() -> LogLevel.ALL
79-
kLogger.isLoggingOff() -> LogLevel.NONE
80-
else -> LogLevel.INFO
81-
}
82-
83-
logger =
84-
object : Logger {
85-
override fun log(message: String) {
86-
kLogger.info { message }
87-
}
88-
}
89-
format = LoggingFormat.OkHttp
90-
sanitizeHeader { header -> header == HttpHeaders.Authorization }
91-
92-
// filter { it.url.host.contains("localhost").not() }
93-
}
94-
95-
engine {
96-
pipelining = true
97-
// proxy = ProxyBuilder.http()
98-
}
99-
100-
followRedirects = true
101-
102-
install(UserAgent) { agent = "$name-${BuildConfig.version}" }
103-
104-
install(DefaultRequest) {
105-
headers.appendIfNameAndValueAbsent(
106-
HttpHeaders.ContentType, ContentType.Application.Json.toString())
107-
}
108-
109-
install(SSE) {
110-
maxReconnectionAttempts = retry.attempts
111-
reconnectionTime = timeout.connection
112-
}
113-
114-
install(WebSockets) { pingInterval = timeout.read }
115-
116-
expectSuccess = true
117-
118-
// install(SaveBodyPlugin) {
119-
// disabled = true
120-
// }
121-
122-
HttpResponseValidator {
123-
handleResponseExceptionWithRequest { ex, req ->
124-
val resException = ex as? ResponseException ?: return@handleResponseExceptionWithRequest
125-
val res = resException.response
126-
kLogger.trace { "Request failed: ${req.method.value} ${req.url} -> ${res.status}" }
51+
config: HttpClientConfigurer = defaultHttpClientConfig(name, timeout, retry, kLogger)
52+
): HttpClient
53+
54+
fun defaultHttpClientConfig(
55+
name: String,
56+
timeout: Timeout,
57+
retry: Retry,
58+
kLogger: KLogger
59+
): HttpClientConfigurer = {
60+
install(Resources)
61+
install(ContentNegotiation) { json(json) }
62+
install(ContentEncoding) {
63+
deflate(1.0F)
64+
gzip(0.9F)
65+
}
66+
67+
install(HttpRequestRetry) {
68+
maxRetries = retry.attempts
69+
retryOnException(retryOnTimeout = true)
70+
retryOnServerErrors()
71+
exponentialDelay(maxDelayMs = retry.maxDelay.inWholeMilliseconds)
72+
// modifyRequest { it.headers.append("X_RETRY_COUNT", retryCount.toString()) }
73+
}
74+
75+
install(HttpTimeout) {
76+
connectTimeoutMillis = timeout.connection.inWholeMilliseconds
77+
requestTimeoutMillis = timeout.read.inWholeMilliseconds
78+
socketTimeoutMillis = timeout.write.inWholeMilliseconds
79+
}
80+
81+
install(HttpCookies)
82+
83+
install(Logging) {
84+
level =
85+
when {
86+
kLogger.isDebugEnabled() -> LogLevel.ALL
87+
kLogger.isLoggingOff() -> LogLevel.NONE
88+
else -> LogLevel.INFO
12789
}
128-
}
90+
91+
logger =
92+
object : Logger {
93+
override fun log(message: String) {
94+
kLogger.info { message }
95+
}
96+
}
97+
format = LoggingFormat.OkHttp
98+
sanitizeHeader { header -> header == HttpHeaders.Authorization }
99+
// filter { it.url.host.contains("localhost").not() }
100+
}
101+
102+
engine {
103+
pipelining = true
104+
// proxy = ProxyBuilder.http()
105+
}
106+
107+
followRedirects = true
108+
109+
install(UserAgent) { agent = "$name-${BuildConfig.version}" }
110+
111+
install(DefaultRequest) {
112+
headers.appendIfNameAndValueAbsent(
113+
HttpHeaders.ContentType, ContentType.Application.Json.toString())
114+
}
115+
116+
install(SSE) {
117+
maxReconnectionAttempts = retry.attempts
118+
reconnectionTime = timeout.connection
119+
}
120+
121+
install(WebSockets) { pingInterval = timeout.read }
122+
123+
expectSuccess = true
124+
125+
// install(SaveBodyPlugin) {
126+
// disabled = true
127+
// }
128+
129+
HttpResponseValidator {
130+
handleResponseExceptionWithRequest { ex, req ->
131+
val resException = ex as? ResponseException ?: return@handleResponseExceptionWithRequest
132+
val res = resException.response
133+
kLogger.trace { "Request failed: ${req.method.value} ${req.url} -> ${res.status}" }
129134
}
130-
): HttpClient
135+
}
136+
}

shared/src/jsMain/kotlin/dev/suresh/http/HttpClient.js.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ actual fun httpClient(
99
timeout: Timeout,
1010
retry: Retry,
1111
kLogger: KLogger,
12-
config: HttpClientConfig<*>.() -> Unit
12+
config: HttpClientConfigurer
1313
) = HttpClient(Js) { config(this) }
1414

1515
fun getKtorEnvLogLevel(): String? = js("process.env.KTOR_LOG_LEVEL")

shared/src/jvmMain/kotlin/dev/suresh/http/HttpClient.jvm.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ actual fun httpClient(
2424
timeout: Timeout,
2525
retry: Retry,
2626
kLogger: KLogger,
27-
config: HttpClientConfig<*>.() -> Unit
27+
config: HttpClientConfigurer
2828
) =
2929
HttpClient(Java) {
3030
config(this)

shared/src/nativeMain/kotlin/dev/suresh/http/HttpClient.native.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@ actual fun httpClient(
99
timeout: Timeout,
1010
retry: Retry,
1111
kLogger: KLogger,
12-
config: HttpClientConfig<*>.() -> Unit
12+
config: HttpClientConfigurer
1313
) =
1414
HttpClient(Curl) {
1515
config(this)
16-
engine { sslVerify = true }
16+
engine {
17+
// https://youtrack.jetbrains.com/issue/KTOR-8339
18+
if (Platform.osFamily == OsFamily.LINUX) {
19+
caPath = "/etc/ssl/certs"
20+
}
21+
sslVerify = true
22+
}
1723
}

shared/src/wasmJsMain/kotlin/dev/suresh/http/HttpClient.wasmJs.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ actual fun httpClient(
99
timeout: Timeout,
1010
retry: Retry,
1111
kLogger: KLogger,
12-
config: HttpClientConfig<*>.() -> Unit,
12+
config: HttpClientConfigurer,
1313
) = HttpClient(Js) { config(this) }

0 commit comments

Comments
 (0)