Skip to content

Commit e70922e

Browse files
authored
KTOR-9125 Fix double ResponseSent invocation when exception is thrown after respond (#5215)
1 parent 589f02d commit e70922e

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

ktor-server/ktor-server-core/common/src/io/ktor/server/engine/DefaultEnginePipeline.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import io.ktor.server.engine.internal.*
1111
import io.ktor.server.logging.*
1212
import io.ktor.server.plugins.*
1313
import io.ktor.server.response.*
14-
import io.ktor.server.routing.routingCallKey
14+
import io.ktor.server.routing.*
1515
import io.ktor.util.cio.*
1616
import io.ktor.util.logging.*
1717
import io.ktor.util.pipeline.*
1818
import io.ktor.utils.io.*
19-
import kotlinx.coroutines.*
2019
import kotlinx.coroutines.CancellationException
20+
import kotlinx.coroutines.TimeoutCancellationException
2121
import kotlinx.io.IOException
2222

2323
/**
@@ -62,6 +62,8 @@ public fun defaultEnginePipeline(config: ApplicationConfig, developmentMode: Boo
6262
*/
6363
public suspend fun handleFailure(call: ApplicationCall, error: Throwable) {
6464
logError(call, error)
65+
if (call.response.isSent) return
66+
6567
tryRespondError(call, defaultExceptionStatusCode(error) ?: HttpStatusCode.InternalServerError)
6668
}
6769

ktor-server/ktor-server-test-host/common/src/io/ktor/server/testing/TestApplicationEngine.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ public class TestApplicationEngine(
121121

122122
private suspend fun handleTestFailure(call: ApplicationCall, cause: Throwable) {
123123
logError(call, cause)
124+
if (call.response.isSent) return
124125

125126
val throwOnException = environment.config
126127
.propertyOrNull(CONFIG_KEY_THROW_ON_EXCEPTION)

ktor-server/ktor-server-test-suites/common/src/io/ktor/server/testing/suites/HttpServerCommonTestSuite.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,36 @@ abstract class HttpServerCommonTestSuite<TEngine : ApplicationEngine, TConfigura
795795
}
796796
}
797797

798+
@Test
799+
fun testResponseSentCalledOnce() = runTest {
800+
var responseSentCalled = 0
801+
createAndStartServer {
802+
serverConfig {
803+
enableSsl = false
804+
enableHttp2 = false
805+
}
806+
install(
807+
createRouteScopedPlugin("Plugin") {
808+
on(ResponseSent) {
809+
responseSentCalled++
810+
}
811+
}
812+
)
813+
814+
get("/") {
815+
call.respond("ok")
816+
throw ExpectedTestException("exception")
817+
}
818+
}
819+
820+
withUrl("/") {
821+
assertEquals(HttpStatusCode.OK, status)
822+
assertEquals("ok", bodyAsText())
823+
}
824+
delay(500)
825+
assertEquals(1, responseSentCalled)
826+
}
827+
798828
private data class TestData(
799829
val name: String
800830
) : AbstractCoroutineContextElement(TestData) {

0 commit comments

Comments
 (0)