-
Notifications
You must be signed in to change notification settings - Fork 38.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Double error response handling on suspended methods #31541
Comments
I've found out that it's being triggered by setting the attribute ...
if (statusCode.equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
}
... So I'm for now using a workaround by removing that attribute after calling @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
).also {
request.removeAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, WebRequest.SCOPE_REQUEST)
}
}
} |
...
if (request.isAsyncDispatching()) {
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
if (t != null) {
asyncConImpl.setErrorState(t, true);
}
}
... |
Just tested it with Jetty and Undertow. Both handle the exception correctly |
Thanks for tracking that down, @nilskohrs. As the problem occurs with Tomcat but not with Jetty and Undertow, it would appear to be an issue with how Tomcat performs error handling for async requests (/cc @markt-asf). Please turn the steps and code snippets above into a complete yet minimal example and then open a Tomcat issue so that they can investigate. |
Bug reported with Tomcat: https://bz.apache.org/bugzilla/show_bug.cgi?id=66875 |
@wilkinsona you might want to review the Tomcat bug report. There was a Tomcat issue that has been fixed but there might be a Spring issue as well. The |
Thanks, @markt-asf. I'll re-open this and we can transfer it to the Framework team so that they can review the behavior of |
@rstoyanchev according to https://bz.apache.org/bugzilla/show_bug.cgi?id=66875#c11, our |
Hi everyone! based on above #31541 (comment), I create simple fix PR #31953! PTAL when you have some times 🙇 thank you! |
From Mark's comment on the Tomcat issue:
The request attribute was added a long time ago in 48b963a to assist with Servlet container defined error pages, and when it's only the response status that is set, it allows Boot's error handling to add a response body. However, with RFC 7807 responses we now set a response body, and shouldn't be setting the attribute if that's the case. I verified that the fix on Tomcat's side apache/tomcat@276e04f does preclude the additional ERROR dispatch in this scenario, but we can also make a change to not even set the attribute when there is a response body. |
Aha~ thank you @rstoyanchev for kind and detailed explanation! 👍 Anyway I'm big fan of spring-framework and want to contribute continuously so I'll try to resolve another issue~! |
ResponseEntityExceptionHandler should not set the exception attribute when there is a response body, and the response is fully handled. Closes gh-31541
The combination of
spring-boot-starter-web
,kotlinx-coroutines-reactor
, a suspended controller method and handling a 500 error response throughResponseEntityExceptionHandler
causes double exception handling and response bodies.The first response body is generated by the
ProblemDetail
handled withResponseEntityExceptionHandler.handleException(...)
, the second is generated byBasicErrorController
Reproduction steps (tested on version 3.0.0 and 3.1.2):
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.
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.
The text was updated successfully, but these errors were encountered: