https://kotlinlang.org logo
#ktor
Title
# ktor
p

PHaroZ

04/12/2022, 5:13 PM
Hi, I use the ktor client (v1.6.7, jvm platform) with
HttpTimeout
feature ; I try to figure out were I can catch the
HttpRequestTimeoutException
thrown but I don't find any clean and generic solution. Here is my config :
Copy code
val engine = TODO("CIO.create() or MockEngine")
val ktorBaseClient = HttpClient(engine) {
  install(HttpTimeout)
}
val ktorClient = ktorBaseClient.config {
		HttpResponseValidator {
			handleResponseException { t ->
				when (t) {
// -----> next line works with MockEngine but not with CIO.create()
					is HttpRequestTimeoutException -> throw MyCustomException()
					else -> throw t
				}
			}
			validateResponse { response ->
// it doesn't seem do by the right place to catch HttpRequestTimeoutException
				...
            }
        }
}

ktorClient.get("some_uri") {
  timeout { requestTimeoutMillis = 1.seconds.inWholeMilliseconds }
}
Note that to simulate a timeout via the MockEngine I do something like
Copy code
MockEngine {
			delay(2.seconds.inWholeMilliseconds)
			throw IllegalStateException("should never be called")
		}
and it works, it throws a
MyCustomException
; but this is not the case in production code, with the CIO engine. Does someone have any advice or example ? thx for your help.
here is the exception from production code :
Copy code
Caused by: io.ktor.client.features.HttpRequestTimeoutException: Request timeout has expired [url=<http://XXXXXX>, request_timeout=15000 ms]
	at io.ktor.client.features.HttpTimeout$Feature$install$1$1$killer$1.invokeSuspend(HttpTimeout.kt:149)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
a

Aleksei Tirman [JB]

04/12/2022, 8:56 PM
You can wrap your code that makes a request with
try/catch
to catch the
HttpRequestTimeoutException
. Could you please describe what problem are you trying to solve?
p

PHaroZ

04/13/2022, 6:13 AM
My webapp have a bunch of functions that call a webservice, this webservice could take some time to response, so I would like to set a request timeout. When this timeout is hit I would like to return a clean warning message to my end-users. Surrounding the requests with
try/catch
work fine, however I have to implement this logic in each call. I was looking for something more generic if it exists. Thx for your help 🙂
a

Aleksei Tirman [JB]

04/13/2022, 11:36 AM
When a timeout happens the
executionContext
of a request is cancelled with the
HttpRequestTimeoutException
so you can add a handler that will be called when request’s job is completed (with an exception or not). Here is an example:
Copy code
val client = HttpClient(Apache) {
    install(HttpTimeout) {
        requestTimeoutMillis = 1
    }
}

client.requestPipeline.intercept(HttpRequestPipeline.Before) {
    context.executionContext.invokeOnCompletion { cause ->
        if (cause is HttpRequestTimeoutException) {
            println("Warning")
        }
    }
}

client.get<String>("<https://example.com>")
4 Views