mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-26 00:39:01 +00:00
Revise disconnected client error handling in Spring MVC
DisconnectedClientHelper identifies lost connection issues, but it's not always easy to know if it is the connection to the client or to another remote host. DisconnectedClientHelper does recognize and filter out common client exceptions, but there is a possibility for other similar custom exceptions. DefaultHandlerExceptionResolver now attempts to set the status to 500, which won't impact a client that has gone away, but it will set the status correct on the off chance that the exception is actually a server side issue. Closes gh-34481
This commit is contained in:
+20
-6
@@ -167,6 +167,13 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
|
||||
protected static final Log pageNotFoundLogger = LogFactory.getLog(PAGE_NOT_FOUND_LOG_CATEGORY);
|
||||
|
||||
|
||||
private static final String DISCONNECTED_CLIENT_LOG_CATEGORY =
|
||||
"org.springframework.web.servlet.handler.DisconnectedClient";
|
||||
|
||||
private static final DisconnectedClientHelper disconnectedClientHelper =
|
||||
new DisconnectedClientHelper(DISCONNECTED_CLIENT_LOG_CATEGORY);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the {@linkplain #setOrder(int) order} to {@link #LOWEST_PRECEDENCE}.
|
||||
*/
|
||||
@@ -246,7 +253,7 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
|
||||
return handleAsyncRequestNotUsableException(
|
||||
(AsyncRequestNotUsableException) ex, request, response, handler);
|
||||
}
|
||||
else if (DisconnectedClientHelper.isClientDisconnectedException(ex)) {
|
||||
else if (disconnectedClientHelper.checkAndLogClientDisconnectedException(ex)) {
|
||||
return handleDisconnectedClientException(ex, request, response, handler);
|
||||
}
|
||||
}
|
||||
@@ -506,11 +513,11 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an Exception that indicates the client has gone away. This is
|
||||
* typically an {@link IOException} of a specific subtype or with a message
|
||||
* specific to the underlying Servlet container. Those are detected through
|
||||
* {@link DisconnectedClientHelper#isClientDisconnectedException(Throwable)}
|
||||
* <p>By default, do nothing since the response is not usable.
|
||||
* Handle an Exception that indicates the client has gone away as determined
|
||||
* via {@link DisconnectedClientHelper}.
|
||||
* <p>By default, as of 7.1 this method attempts to set the response status
|
||||
* to 500 in case the exception is due to a connection issue to a remote host,
|
||||
* as part of request handling, rather than to the client.
|
||||
* @param ex the {@code Exception} to be handled
|
||||
* @param request current HTTP request
|
||||
* @param response current HTTP response
|
||||
@@ -522,6 +529,13 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
|
||||
protected ModelAndView handleDisconnectedClientException(
|
||||
Exception ex, HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) {
|
||||
|
||||
// Attempt to send 500 in case of onward (rather than client) connection issue
|
||||
try {
|
||||
sendServerError(ex, request, response);
|
||||
}
|
||||
catch (Exception ex2) {
|
||||
// ignore
|
||||
}
|
||||
return new ModelAndView();
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.web.servlet.mvc.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -269,6 +270,14 @@ class DefaultHandlerExceptionResolverTests {
|
||||
assertThat(actual).isSameAs(expected);
|
||||
}
|
||||
|
||||
@Test // gh-34481
|
||||
void handleDisconnectedClientException() {
|
||||
Exception ex = new IOException("Broken pipe");
|
||||
ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex);
|
||||
assertThat(mav).as("No ModelAndView returned").isNotNull();
|
||||
assertThat(mav.isEmpty()).as("No Empty ModelAndView returned").isTrue();
|
||||
assertThat(response.getStatus()).as("Should attempt to send server error").isEqualTo(500);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void handle(String arg) {
|
||||
|
||||
Reference in New Issue
Block a user