mirror of
https://github.com/jlengrand/ktor.git
synced 2026-03-10 08:31:20 +00:00
Prepare exceptions to common sockets
This commit is contained in:
committed by
Leonid Stashevsky
parent
96b59e9c6e
commit
4e5ab80a1d
@@ -6,6 +6,7 @@ package io.ktor.client.engine.android
|
||||
|
||||
import io.ktor.client.features.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.network.sockets.*
|
||||
import io.ktor.util.cio.*
|
||||
import io.ktor.utils.io.*
|
||||
import io.ktor.utils.io.jvm.javaio.*
|
||||
@@ -42,7 +43,7 @@ private fun HttpURLConnection.setupRequestTimeoutAttributes(
|
||||
}
|
||||
|
||||
/**
|
||||
* Call [HttpURLConnection.connect] catching [SocketTimeoutException] and returning [HttpSocketTimeoutException] instead
|
||||
* Call [HttpURLConnection.connect] catching [java.net.SocketTimeoutException] and returning [SocketTimeoutException] instead
|
||||
* of it. If request timeout happens earlier [HttpRequestTimeoutException] will be thrown.
|
||||
*/
|
||||
internal suspend fun HttpURLConnection.timeoutAwareConnect(request: HttpRequestData) {
|
||||
@@ -52,7 +53,7 @@ internal suspend fun HttpURLConnection.timeoutAwareConnect(request: HttpRequestD
|
||||
// Allow to throw request timeout cancellation exception instead of connect timeout exception if needed.
|
||||
yield()
|
||||
throw when (cause) {
|
||||
is SocketTimeoutException -> HttpConnectTimeoutException(request)
|
||||
is java.net.SocketTimeoutException -> ConnectTimeoutException(request, cause)
|
||||
else -> cause
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ internal suspend fun CloseableHttpAsyncClient.sendRequest(
|
||||
val callback = object : FutureCallback<Unit> {
|
||||
override fun failed(exception: Exception) {
|
||||
val mappedCause = when {
|
||||
exception is ConnectException && exception.isTimeoutException() -> HttpConnectTimeoutException(
|
||||
requestData
|
||||
exception is ConnectException && exception.isTimeoutException() -> ConnectTimeoutException(
|
||||
requestData, exception
|
||||
)
|
||||
exception is SocketTimeoutException -> HttpSocketTimeoutException(requestData)
|
||||
exception is java.net.SocketTimeoutException -> SocketTimeoutException(requestData, exception)
|
||||
else -> exception
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ import io.ktor.client.request.*
|
||||
import io.ktor.client.utils.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.http.content.*
|
||||
import io.ktor.utils.io.*
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.*
|
||||
import io.ktor.utils.io.*
|
||||
import org.apache.http.*
|
||||
import org.apache.http.HttpHeaders
|
||||
import org.apache.http.HttpRequest
|
||||
@@ -25,7 +25,7 @@ import org.apache.http.entity.*
|
||||
import org.apache.http.nio.*
|
||||
import org.apache.http.nio.protocol.*
|
||||
import org.apache.http.protocol.*
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.*
|
||||
import kotlin.coroutines.*
|
||||
|
||||
internal class ApacheRequestProducer(
|
||||
@@ -186,7 +186,8 @@ internal class ApacheRequestProducer(
|
||||
|
||||
private fun ByteBuffer.recycle() {
|
||||
if (requestData.body is OutgoingContent.WriteChannelContent ||
|
||||
requestData.body is OutgoingContent.ReadChannelContent) {
|
||||
requestData.body is OutgoingContent.ReadChannelContent
|
||||
) {
|
||||
HttpClientDefaultPool.recycle(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,8 +122,8 @@ internal class ApacheResponseConsumerDispatching(
|
||||
|
||||
override fun failed(cause: Exception) {
|
||||
val mappedCause = when {
|
||||
cause is ConnectException && cause.isTimeoutException() -> HttpConnectTimeoutException(requestData!!)
|
||||
cause is SocketTimeoutException -> HttpSocketTimeoutException(requestData!!)
|
||||
cause is ConnectException && cause.isTimeoutException() -> ConnectTimeoutException(requestData!!, cause)
|
||||
cause is java.net.SocketTimeoutException -> SocketTimeoutException(requestData!!, cause)
|
||||
else -> cause
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ internal class Endpoint(
|
||||
response.resume(responseData)
|
||||
} catch (cause: Throwable) {
|
||||
val mappedException = when (cause.rootCause) {
|
||||
is SocketTimeoutException -> HttpSocketTimeoutException(task.request)
|
||||
is java.net.SocketTimeoutException -> SocketTimeoutException(task.request, cause)
|
||||
else -> cause
|
||||
}
|
||||
response.resumeWithException(mappedException)
|
||||
@@ -210,7 +210,7 @@ internal class Endpoint(
|
||||
*/
|
||||
private fun getTimeoutException(retryAttempts: Int, timeoutFails: Int, request: HttpRequestData) =
|
||||
when (timeoutFails) {
|
||||
retryAttempts -> HttpConnectTimeoutException(request)
|
||||
retryAttempts -> ConnectTimeoutException(request)
|
||||
else -> FailToConnectException()
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ package io.ktor.client.features
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.engine.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.network.sockets.*
|
||||
import io.ktor.util.*
|
||||
import io.ktor.utils.io.errors.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
@@ -141,22 +141,38 @@ fun HttpRequestBuilder.timeout(block: HttpTimeout.HttpTimeoutCapabilityConfigura
|
||||
/**
|
||||
* This exception is thrown in case request timeout exceeded.
|
||||
*/
|
||||
class HttpRequestTimeoutException(request: HttpRequestBuilder) :
|
||||
CancellationException(
|
||||
"Request timeout has been expired [url=${request.url}, request_timeout=${request.getCapabilityOrNull(
|
||||
HttpTimeout
|
||||
)?.requestTimeoutMillis ?: "unknown"} ms]"
|
||||
)
|
||||
class HttpRequestTimeoutException(
|
||||
request: HttpRequestBuilder
|
||||
) : CancellationException(
|
||||
"Request timeout has been expired [url=${request.url}, request_timeout=${request.getCapabilityOrNull(
|
||||
HttpTimeout
|
||||
)?.requestTimeoutMillis ?: "unknown"} ms]"
|
||||
)
|
||||
|
||||
/**
|
||||
* This exception is thrown in case connect timeout exceeded.
|
||||
*/
|
||||
expect class HttpConnectTimeoutException(request: HttpRequestData) : IOException
|
||||
fun ConnectTimeoutException(
|
||||
request: HttpRequestData, cause: Throwable? = null
|
||||
): ConnectTimeoutException = ConnectTimeoutException(
|
||||
"Connect timeout has been expired [url=${request.url}, connect_timeout=${request.getCapabilityOrNull(
|
||||
HttpTimeout
|
||||
)?.connectTimeoutMillis ?: "unknown"} ms]",
|
||||
cause
|
||||
)
|
||||
|
||||
/**
|
||||
* This exception is thrown in case socket timeout (read or write) exceeded.
|
||||
*/
|
||||
expect class HttpSocketTimeoutException(request: HttpRequestData) : IOException
|
||||
fun SocketTimeoutException(
|
||||
request: HttpRequestData,
|
||||
cause: Throwable? = null
|
||||
): SocketTimeoutException = SocketTimeoutException(
|
||||
"Socket timeout has been expired [url=${request.url}, socket_timeout=${request.getCapabilityOrNull(
|
||||
HttpTimeout
|
||||
)?.socketTimeoutMillis ?: "unknown"}] ms",
|
||||
cause
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert long timeout in milliseconds to int value. To do that we need to consider [HttpTimeout.INFINITE_TIMEOUT_MS]
|
||||
@@ -170,6 +186,10 @@ fun convertLongTimeoutToIntWithInfiniteAsZero(timeout: Long): Int = when {
|
||||
else -> timeout.toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert long timeout in milliseconds to long value. To do that we need to consider [HttpTimeout.INFINITE_TIMEOUT_MS]
|
||||
* as zero and convert timeout value to [Int].
|
||||
*/
|
||||
@InternalAPI
|
||||
fun convertLongTimeoutToLongWithInfiniteAsZero(timeout: Long): Long = when (timeout) {
|
||||
HttpTimeout.INFINITE_TIMEOUT_MS -> 0L
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2014-2020 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
package io.ktor.network.sockets
|
||||
|
||||
import io.ktor.utils.io.errors.*
|
||||
|
||||
/**
|
||||
* This exception is thrown in case connect timeout exceeded.
|
||||
*/
|
||||
expect class ConnectTimeoutException(message: String, cause: Throwable? = null) : IOException
|
||||
|
||||
/**
|
||||
* This exception is thrown in case socket timeout (read or write) exceeded.
|
||||
*/
|
||||
expect class SocketTimeoutException(message: String, cause: Throwable? = null) : IOException
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
package io.ktor.client.features
|
||||
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.utils.io.errors.*
|
||||
|
||||
/**
|
||||
* HTTP connect timeout exception.
|
||||
*/
|
||||
@Suppress("ACTUAL_WITHOUT_EXPECT")
|
||||
actual class HttpConnectTimeoutException actual constructor(request: HttpRequestData) :
|
||||
IOException(
|
||||
"Connect timeout has been expired [url=${request.url}, connect_timeout=${request.getCapabilityOrNull(
|
||||
HttpTimeout
|
||||
)?.connectTimeoutMillis ?: "unknown"} ms]"
|
||||
)
|
||||
|
||||
/**
|
||||
* HTTP socket timeout exception.
|
||||
*/
|
||||
@Suppress("ACTUAL_WITHOUT_EXPECT")
|
||||
actual class HttpSocketTimeoutException actual constructor(request: HttpRequestData) :
|
||||
IOException(
|
||||
"Socket timeout has been expired [url=${request.url}, socket_timeout=${request.getCapabilityOrNull(
|
||||
HttpTimeout
|
||||
)?.socketTimeoutMillis ?: "unknown"}] ms"
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2014-2020 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
package io.ktor.network.sockets
|
||||
|
||||
import io.ktor.utils.io.errors.*
|
||||
|
||||
/**
|
||||
* This exception is thrown in case connect timeout exceeded.
|
||||
*/
|
||||
actual class ConnectTimeoutException actual constructor(
|
||||
message: String, cause: Throwable?
|
||||
) : IOException(message, cause)
|
||||
|
||||
/**
|
||||
* This exception is thrown in case socket timeout (read or write) exceeded.
|
||||
*/
|
||||
actual class SocketTimeoutException actual constructor(
|
||||
message: String, cause: Throwable?
|
||||
) : IOException(message, cause)
|
||||
@@ -1,33 +1,35 @@
|
||||
/*
|
||||
* Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
* Copyright 2014-2020 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
package io.ktor.client.features
|
||||
package io.ktor.network.sockets
|
||||
|
||||
import io.ktor.client.features.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.util.*
|
||||
import io.ktor.utils.io.*
|
||||
import kotlinx.coroutines.*
|
||||
import java.net.*
|
||||
|
||||
/**
|
||||
* This exception is thrown in case connect timeout exceeded.
|
||||
*/
|
||||
@Suppress("ACTUAL_WITHOUT_EXPECT")
|
||||
actual class HttpConnectTimeoutException actual constructor(request: HttpRequestData) :
|
||||
ConnectException(
|
||||
"Connect timeout has been expired [url=${request.url}, connect_timeout=${request.getCapabilityOrNull(
|
||||
HttpTimeout
|
||||
)?.connectTimeoutMillis ?: "unknown"} ms]"
|
||||
)
|
||||
|
||||
@Suppress("ACTUAL_WITHOUT_EXPECT")
|
||||
actual class HttpSocketTimeoutException actual constructor(request: HttpRequestData) :
|
||||
SocketTimeoutException(
|
||||
"Socket timeout has been expired [url=${request.url}, socket_timeout=${request.getCapabilityOrNull(
|
||||
HttpTimeout
|
||||
)?.socketTimeoutMillis ?: "unknown"}] ms"
|
||||
)
|
||||
actual class ConnectTimeoutException actual constructor(
|
||||
message: String, override val cause: Throwable?
|
||||
) : ConnectException(message) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [ByteReadChannel] with [ByteChannel.close] handler that returns [HttpSocketTimeoutException] instead of
|
||||
* This exception is thrown in case socket timeout (read or write) exceeded.
|
||||
*/
|
||||
@Suppress("ACTUAL_WITHOUT_EXPECT")
|
||||
actual class SocketTimeoutException actual constructor(
|
||||
message: String, override val cause: Throwable?
|
||||
) : java.net.SocketTimeoutException(message)
|
||||
|
||||
/**
|
||||
* Returns [ByteReadChannel] with [ByteChannel.close] handler that returns [SocketTimeoutException] instead of
|
||||
* [SocketTimeoutException].
|
||||
*/
|
||||
@InternalAPI
|
||||
@@ -46,7 +48,7 @@ fun CoroutineScope.mapEngineExceptions(input: ByteReadChannel, request: HttpRequ
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [ByteWriteChannel] with [ByteChannel.close] handler that returns [HttpSocketTimeoutException] instead of
|
||||
* Returns [ByteWriteChannel] with [ByteChannel.close] handler that returns [SocketTimeoutException] instead of
|
||||
* [SocketTimeoutException].
|
||||
*/
|
||||
@InternalAPI
|
||||
@@ -65,12 +67,12 @@ fun CoroutineScope.mapEngineExceptions(input: ByteWriteChannel, request: HttpReq
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates [ByteChannel] that maps close exceptions (close the channel with [HttpSocketTimeoutException] if asked to
|
||||
* Creates [ByteChannel] that maps close exceptions (close the channel with [SocketTimeoutException] if asked to
|
||||
* close it with [SocketTimeoutException]).
|
||||
*/
|
||||
private fun ByteChannelWithMappedExceptions(request: HttpRequestData) = ByteChannel { cause ->
|
||||
when (cause?.rootCause) {
|
||||
is SocketTimeoutException -> HttpSocketTimeoutException(request)
|
||||
is java.net.SocketTimeoutException -> SocketTimeoutException(request, cause)
|
||||
else -> cause
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
package io.ktor.client.features
|
||||
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.utils.io.errors.*
|
||||
|
||||
/**
|
||||
* HTTP connect timeout exception.
|
||||
*/
|
||||
@Suppress("ACTUAL_WITHOUT_EXPECT")
|
||||
actual class HttpConnectTimeoutException actual constructor(request: HttpRequestData) :
|
||||
IOException(
|
||||
"Connect timeout has been expired [url=${request.url}, connect_timeout=${request.getCapabilityOrNull(
|
||||
HttpTimeout
|
||||
)?.connectTimeoutMillis ?: "unknown"} ms]"
|
||||
)
|
||||
|
||||
/**
|
||||
* HTTP socket timeout exception.
|
||||
*/
|
||||
@Suppress("ACTUAL_WITHOUT_EXPECT")
|
||||
actual class HttpSocketTimeoutException actual constructor(request: HttpRequestData) :
|
||||
IOException(
|
||||
"Socket timeout has been expired [url=${request.url}, socket_timeout=${request.getCapabilityOrNull(
|
||||
HttpTimeout
|
||||
)?.socketTimeoutMillis ?: "unknown"}] ms"
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2014-2020 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
package io.ktor.network.sockets
|
||||
|
||||
import io.ktor.utils.io.errors.*
|
||||
|
||||
/**
|
||||
* This exception is thrown in case connect timeout exceeded.
|
||||
*/
|
||||
actual class ConnectTimeoutException actual constructor(
|
||||
message: String, cause: Throwable?
|
||||
) : IOException(message, cause)
|
||||
|
||||
/**
|
||||
* This exception is thrown in case socket timeout (read or write) exceeded.
|
||||
*/
|
||||
actual class SocketTimeoutException actual constructor(
|
||||
message: String, cause: Throwable?
|
||||
) : IOException(message, cause)
|
||||
@@ -6,6 +6,7 @@ package io.ktor.client.engine.curl.internal
|
||||
|
||||
import io.ktor.client.engine.curl.*
|
||||
import io.ktor.client.features.*
|
||||
import io.ktor.network.sockets.*
|
||||
import kotlinx.cinterop.*
|
||||
import io.ktor.utils.io.core.*
|
||||
import libcurl.*
|
||||
@@ -204,7 +205,7 @@ internal class CurlMultiApiHandler : Closeable {
|
||||
if (result == CURLE_OPERATION_TIMEDOUT) {
|
||||
return CurlFail(
|
||||
responseBuilder.request,
|
||||
HttpConnectTimeoutException(responseBuilder.request.requestData)
|
||||
ConnectTimeoutException(responseBuilder.request.requestData)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ internal class IosClientEngine(override val config: IosClientEngineConfig) : Htt
|
||||
|
||||
if (didCompleteWithError != null) {
|
||||
val mappedException = when (didCompleteWithError.code) {
|
||||
NSURLErrorTimedOut -> HttpSocketTimeoutException(data)
|
||||
NSURLErrorTimedOut -> SocketTimeoutException(data)
|
||||
else -> IosHttpRequestException(didCompleteWithError)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,15 +11,15 @@ import io.ktor.client.request.*
|
||||
import io.ktor.client.utils.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.http.content.*
|
||||
import io.ktor.network.sockets.*
|
||||
import io.ktor.util.*
|
||||
import io.ktor.util.date.*
|
||||
import kotlinx.coroutines.*
|
||||
import io.ktor.utils.io.*
|
||||
import kotlinx.coroutines.*
|
||||
import okhttp3.*
|
||||
import okhttp3.internal.http.HttpMethod
|
||||
import okio.*
|
||||
import java.io.*
|
||||
import java.net.*
|
||||
import java.util.concurrent.*
|
||||
import kotlin.coroutines.*
|
||||
|
||||
@@ -149,8 +149,8 @@ private fun BufferedSource.toChannel(context: CoroutineContext, requestData: Htt
|
||||
}
|
||||
}.channel
|
||||
|
||||
private fun mapExceptions(cause: Throwable, request: HttpRequestData) = when (cause) {
|
||||
is SocketTimeoutException -> HttpSocketTimeoutException(request)
|
||||
private fun mapExceptions(cause: Throwable, request: HttpRequestData): Throwable = when (cause) {
|
||||
is java.net.SocketTimeoutException -> SocketTimeoutException(request, cause)
|
||||
else -> cause
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import kotlinx.coroutines.*
|
||||
import okhttp3.*
|
||||
import okhttp3.Headers
|
||||
import java.io.*
|
||||
import java.net.*
|
||||
import kotlin.coroutines.*
|
||||
|
||||
internal suspend fun OkHttpClient.execute(request: Request, requestData: HttpRequestData): Response =
|
||||
@@ -25,10 +24,10 @@ internal suspend fun OkHttpClient.execute(request: Request, requestData: HttpReq
|
||||
}
|
||||
|
||||
val mappedException = when (cause) {
|
||||
is SocketTimeoutException -> if (cause.message?.contains("connect") == true) {
|
||||
HttpConnectTimeoutException(requestData)
|
||||
is java.net.SocketTimeoutException -> if (cause.message?.contains("connect") == true) {
|
||||
ConnectTimeoutException(requestData, cause)
|
||||
} else {
|
||||
HttpSocketTimeoutException(requestData)
|
||||
SocketTimeoutException(requestData, cause)
|
||||
}
|
||||
else -> cause
|
||||
}
|
||||
|
||||
@@ -10,4 +10,4 @@ import io.ktor.util.*
|
||||
* Check that [block] completed with given type of root cause.
|
||||
*/
|
||||
@InternalAPI
|
||||
expect inline fun <reified T : Throwable> assertFailsWithRootCause(block: () -> Unit)
|
||||
expect inline fun <reified T : Throwable> assertFailsAndContainsCause(block: () -> Unit)
|
||||
|
||||
@@ -10,6 +10,7 @@ import io.ktor.client.request.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.client.tests.utils.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.network.sockets.*
|
||||
import io.ktor.utils.io.*
|
||||
import io.ktor.utils.io.core.*
|
||||
import kotlinx.coroutines.*
|
||||
@@ -101,7 +102,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpRequestTimeoutException> {
|
||||
assertFailsAndContainsCause<HttpRequestTimeoutException> {
|
||||
client.head<HttpResponse>("$TEST_URL/with-delay?delay=1000")
|
||||
}
|
||||
}
|
||||
@@ -208,7 +209,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
method = HttpMethod.Get
|
||||
parameter("delay", 500)
|
||||
}
|
||||
assertFailsWithRootCause<HttpRequestTimeoutException> {
|
||||
assertFailsAndContainsCause<HttpRequestTimeoutException> {
|
||||
response.readUTF8Line()
|
||||
}
|
||||
}
|
||||
@@ -227,7 +228,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
|
||||
timeout { requestTimeoutMillis = 1000 }
|
||||
}
|
||||
assertFailsWithRootCause<HttpRequestTimeoutException> {
|
||||
assertFailsAndContainsCause<HttpRequestTimeoutException> {
|
||||
response.readUTF8Line()
|
||||
}
|
||||
}
|
||||
@@ -272,7 +273,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpRequestTimeoutException> {
|
||||
assertFailsAndContainsCause<HttpRequestTimeoutException> {
|
||||
client.get<ByteArray>("$TEST_URL/with-stream") {
|
||||
parameter("delay", 200)
|
||||
}
|
||||
@@ -287,7 +288,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpRequestTimeoutException> {
|
||||
assertFailsAndContainsCause<HttpRequestTimeoutException> {
|
||||
client.get<ByteArray>("$TEST_URL/with-stream") {
|
||||
parameter("delay", 200)
|
||||
|
||||
@@ -337,7 +338,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpRequestTimeoutException> {
|
||||
assertFailsAndContainsCause<HttpRequestTimeoutException> {
|
||||
client.get<String>("$TEST_URL/with-redirect") {
|
||||
parameter("delay", 500)
|
||||
parameter("count", 5)
|
||||
@@ -353,7 +354,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpRequestTimeoutException> {
|
||||
assertFailsAndContainsCause<HttpRequestTimeoutException> {
|
||||
client.get<String>("$TEST_URL/with-redirect") {
|
||||
parameter("delay", 500)
|
||||
parameter("count", 5)
|
||||
@@ -371,7 +372,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpRequestTimeoutException> {
|
||||
assertFailsAndContainsCause<HttpRequestTimeoutException> {
|
||||
client.get<String>("$TEST_URL/with-redirect") {
|
||||
parameter("delay", 250)
|
||||
parameter("count", 5)
|
||||
@@ -387,7 +388,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpRequestTimeoutException> {
|
||||
assertFailsAndContainsCause<HttpRequestTimeoutException> {
|
||||
client.get<String>("$TEST_URL/with-redirect") {
|
||||
parameter("delay", 250)
|
||||
parameter("count", 5)
|
||||
@@ -405,7 +406,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpConnectTimeoutException> {
|
||||
assertFailsAndContainsCause<ConnectTimeoutException> {
|
||||
client.get<String>("http://www.google.com:81")
|
||||
}
|
||||
}
|
||||
@@ -421,7 +422,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
assertFails {
|
||||
try {
|
||||
client.get<String>("http://localhost:11")
|
||||
} catch (_: HttpConnectTimeoutException) {
|
||||
} catch (_: ConnectTimeoutException) {
|
||||
/* Ignore. */
|
||||
}
|
||||
}
|
||||
@@ -435,7 +436,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpConnectTimeoutException> {
|
||||
assertFailsAndContainsCause<ConnectTimeoutException> {
|
||||
client.get<String>("http://www.google.com:81") {
|
||||
timeout { connectTimeoutMillis = 1000 }
|
||||
}
|
||||
@@ -450,7 +451,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpSocketTimeoutException> {
|
||||
assertFailsAndContainsCause<SocketTimeoutException> {
|
||||
client.get<String>("$TEST_URL/with-stream") {
|
||||
parameter("delay", 5000)
|
||||
}
|
||||
@@ -465,7 +466,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpSocketTimeoutException> {
|
||||
assertFailsAndContainsCause<SocketTimeoutException> {
|
||||
client.get<String>("$TEST_URL/with-stream") {
|
||||
parameter("delay", 5000)
|
||||
|
||||
@@ -482,7 +483,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpSocketTimeoutException> {
|
||||
assertFailsAndContainsCause<SocketTimeoutException> {
|
||||
client.post("$TEST_URL/slow-read") { body = makeString(4 * 1024 * 1024) }
|
||||
}
|
||||
}
|
||||
@@ -495,7 +496,7 @@ class HttpTimeoutTest : ClientLoader() {
|
||||
}
|
||||
|
||||
test { client ->
|
||||
assertFailsWithRootCause<HttpSocketTimeoutException> {
|
||||
assertFailsAndContainsCause<SocketTimeoutException> {
|
||||
client.post("$TEST_URL/slow-read") {
|
||||
body = makeString(4 * 1024 * 1024)
|
||||
timeout { socketTimeoutMillis = 500 }
|
||||
|
||||
@@ -10,7 +10,7 @@ import io.ktor.util.*
|
||||
* Check that [block] completed with given type of root cause.
|
||||
*/
|
||||
@InternalAPI
|
||||
actual inline fun <reified T : Throwable> assertFailsWithRootCause(block: () -> Unit) {
|
||||
actual inline fun <reified T : Throwable> assertFailsAndContainsCause(block: () -> Unit) {
|
||||
try {
|
||||
block()
|
||||
error("Expected ${T::class} exception, but it wasn't thrown")
|
||||
|
||||
@@ -11,10 +11,12 @@ import kotlin.test.*
|
||||
* Check that [block] completed with given type of root cause.
|
||||
*/
|
||||
@InternalAPI
|
||||
actual inline fun <reified T : Throwable> assertFailsWithRootCause(block: () -> Unit) {
|
||||
actual inline fun <reified T : Throwable> assertFailsAndContainsCause(block: () -> Unit) {
|
||||
var cause = assertFails(block)
|
||||
while (cause.cause != null) {
|
||||
cause = cause.cause!!
|
||||
|
||||
while(true) {
|
||||
if (cause is T) return
|
||||
cause = cause.cause ?: break
|
||||
}
|
||||
|
||||
assertTrue("Expected root cause is ${T::class}, but got ${cause::class}") { cause is T }
|
||||
|
||||
@@ -18,7 +18,7 @@ abstract class TestWithKtor {
|
||||
protected val serverPort: Int = ServerSocket(0).use { it.localPort }
|
||||
|
||||
@get:Rule
|
||||
open val timeout = CoroutinesTimeout.seconds(3 * 60)
|
||||
open val timeout = CoroutinesTimeout.seconds(5 * 60)
|
||||
|
||||
abstract val server: ApplicationEngine
|
||||
|
||||
|
||||
@@ -11,10 +11,12 @@ import kotlin.test.*
|
||||
* Check that [block] completed with given type of root cause.
|
||||
*/
|
||||
@InternalAPI
|
||||
actual inline fun <reified T : Throwable> assertFailsWithRootCause(block: () -> Unit) {
|
||||
actual inline fun <reified T : Throwable> assertFailsAndContainsCause(block: () -> Unit) {
|
||||
var cause = assertFails(block)
|
||||
|
||||
while (cause.cause != null) {
|
||||
cause = cause.cause!!
|
||||
if (cause is T) return
|
||||
}
|
||||
|
||||
assertTrue("Expected root cause is ${T::class}, but got ${cause::class}") { cause is T }
|
||||
|
||||
Reference in New Issue
Block a user