Coverage Summary for Class: HttpClientKt (dev.suresh.http)

Class Class, % Method, % Branch, % Line, % Instruction, %
HttpClientKt 100% (1/1) 100% (3/3) 100% (13/13) 100% (46/46)


 package dev.suresh.http
 
 import dev.suresh.log
 import io.github.oshai.kotlinlogging.KLogger
 import io.ktor.client.*
 import io.ktor.client.plugins.*
 import io.ktor.client.plugins.compression.*
 import io.ktor.client.plugins.contentnegotiation.*
 import io.ktor.client.plugins.cookies.*
 import io.ktor.client.plugins.logging.*
 import io.ktor.client.plugins.resources.*
 import io.ktor.http.*
 import io.ktor.serialization.kotlinx.json.*
 import io.ktor.util.*
 import kotlinx.serialization.json.ClassDiscriminatorMode.POLYMORPHIC
 import kotlinx.serialization.json.Json
 
 /** Common JSON instance for serde of JSON data. */
 val json by lazy {
   Json {
     prettyPrint = true
     isLenient = true
     ignoreUnknownKeys = true
     encodeDefaults = true
     explicitNulls = false
     decodeEnumsCaseInsensitive = true
     allowTrailingComma = true
     allowSpecialFloatingPointValues = true
     allowStructuredMapKeys = true
     allowComments = true
     classDiscriminatorMode = POLYMORPHIC
   }
 }
 
 /** Multiplatform HTTP client factory function. */
 expect fun httpClient(
     name: String = "Api Client",
     timeout: Timeout = Timeout.DEFAULT,
     retry: Retry = Retry.DEFAULT,
     httpLogger: KLogger = log,
     config: HttpClientConfig<*>.() -> Unit = {
       install(Resources)
 
       install(ContentNegotiation) { json(json) }
 
       install(ContentEncoding) {
         deflate(1.0F)
         gzip(0.9F)
       }
 
       install(HttpRequestRetry) {
         maxRetries = retry.attempts
         retryOnException(retryOnTimeout = true)
         retryOnServerErrors()
         exponentialDelay(maxDelayMs = retry.maxDelay.inWholeMilliseconds)
       }
 
       install(HttpTimeout) {
         connectTimeoutMillis = timeout.connection.inWholeMilliseconds
         requestTimeoutMillis = timeout.read.inWholeMilliseconds
         socketTimeoutMillis = timeout.write.inWholeMilliseconds
       }
 
       install(HttpCookies)
 
       install(Logging) {
         level =
             when {
               httpLogger.isDebugEnabled() -> LogLevel.ALL
               httpLogger.isLoggingOff() -> LogLevel.NONE
               else -> LogLevel.INFO
             }
 
         logger =
             object : Logger {
               override fun log(message: String) {
                 httpLogger.info { message }
               }
             }
         sanitizeHeader { header -> header == HttpHeaders.Authorization }
       }
 
       engine { pipelining = true }
 
       followRedirects = true
 
       install(UserAgent) { agent = "$name-${BuildConfig.version}" }
 
       install(DefaultRequest) {
         headers.appendIfNameAndValueAbsent(
             HttpHeaders.ContentType, ContentType.Application.Json.toString())
       }
 
       expectSuccess = true
 
       HttpResponseValidator {
         handleResponseExceptionWithRequest { ex, req ->
           val resException = ex as? ResponseException ?: return@handleResponseExceptionWithRequest
           val res = resException.response
           httpLogger.trace { "Request failed: ${req.method.value} ${req.url} -> ${res.status}" }
         }
       }
     }
 ): HttpClient