-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Description
The combination of spring-boot-starter-web
, kotlinx-coroutines-reactor
, a suspended controller method and handling a 500 error response through ResponseEntityExceptionHandler
causes double exception handling and response bodies.
The first response body is generated by the ProblemDetail
handled with ResponseEntityExceptionHandler.handleException(...)
, the second is generated by BasicErrorController
Reproduction steps (tested on version 3.0.0 and 3.1.2):
- Create spring initializr project with Kotlin and spring-boot-starter-web
- Add org.jetbrains.kotlinx:kotlinx-coroutines-reactor dependency
- Run following code
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
@RestController
class Controller {
@GetMapping("normal")
fun normalScenario() {
throw IllegalStateException("Returns problemdetail")
}
@GetMapping("suspend")
suspend fun errorScenario() {
throw IllegalStateException("Double exception handling")
}
}
@ControllerAdvice
class ExceptionHandler : ResponseEntityExceptionHandler() {
@ExceptionHandler(Exception::class)
fun handleUnexpectedTechnicalException(
ex: Exception,
request: WebRequest
): ResponseEntity<Any>? {
return handleException(
ErrorResponseException(
HttpStatus.INTERNAL_SERVER_ERROR,
ProblemDetail.forStatus(500),
ex
), request
)
}
}
Endpoint /normal returns the expected Problem Detail
Endpoint /suspend with postman returns double body response (body size + ProblemDetail and then body size + BasicErrorController's response). Since this response is an invalid http response, a proxy like fiddler is needed to see this double response being returned.
HTTP/1.1 500
Content-Type: application/problem+json
Transfer-Encoding: chunked
Date: Tue, 08 Aug 2023 09:26:30 GMT
Connection: close
59
{"type":"about:blank","title":"Internal Server Error","status":500,"instance":"/suspend"}
6c
{"timestamp":"2023-08-08T09:26:30.705+00:00","status":500,"error":"Internal Server Error","path":"/suspend"}
Endpoint /suspend with chrome triggers following error:
s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/suspend] as the response has already been committed. As a result, the response may have the wrong status code.