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

Class Class, % Method, % Branch, % Line, % Instruction, %
HttpClientKt 100% (1/1) 100% (3/3) 100% (14/14) 100% (49/49)


 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.client.plugins.sse.SSE
 import io.ktor.client.plugins.websocket.WebSockets
 import io.ktor.client.plugins.websocket.pingInterval
 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
     coerceInputValues = true
     decodeEnumsCaseInsensitive = true
     allowTrailingComma = true
     allowSpecialFloatingPointValues = true
     allowStructuredMapKeys = true
     allowComments = true
     classDiscriminatorMode = POLYMORPHIC
   }
 }
 
 /**
  * Multiplatform HTTP client engine configuration
  *
  * See [doc](https://ktor.io/docs/client-engines.html#mpp-config) for more details.
  */
 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)
         // modifyRequest { it.headers.append("X_RETRY_COUNT", retryCount.toString()) }
       }
 
       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 }
               }
             }
         format = LoggingFormat.OkHttp
         sanitizeHeader { header -> header == HttpHeaders.Authorization }
 
         // filter { it.url.host.contains("localhost").not() }
       }
 
       engine {
         pipelining = true
         // proxy  = ProxyBuilder.http()
       }
 
       followRedirects = true
 
       install(UserAgent) { agent = "$name-${BuildConfig.version}" }
 
       install(DefaultRequest) {
         headers.appendIfNameAndValueAbsent(
             HttpHeaders.ContentType, ContentType.Application.Json.toString())
       }
 
       install(SSE) {
         maxReconnectionAttempts = retry.attempts
         reconnectionTime = timeout.connection
       }
 
       install(WebSockets) { pingInterval = timeout.read }
 
       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