From b4fd36b4b0c0232e4742c0ebe31d272603a56ebc Mon Sep 17 00:00:00 2001 From: lihan Date: Thu, 24 Aug 2023 11:46:47 +0800 Subject: [PATCH] Attempt to reset Servlet response before calling ExceptionHandlers --- .../ExceptionHandlerExceptionResolver.java | 5 +++++ ...ExceptionHandlerExceptionResolverTests.java | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java index 067fb5af9cec..10630a37a34d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java @@ -399,6 +399,11 @@ protected ModelAndView doResolveHandlerMethodException(HttpServletRequest reques exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } + // attempt to reset the response, as maybe a partial successful response is being written. + if (!response.isCommitted()) { + response.reset(); + } + ServletWebRequest webRequest = new ServletWebRequest(request, response); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java index f28c4759519f..41aadbade4a8 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java @@ -436,6 +436,24 @@ void resolveExceptionViaMappedHandler() throws Exception { assertThat(this.response.getContentAsString()).isEqualTo("DefaultTestExceptionResolver: IllegalStateException"); } + @Test // gh-30702 + void attemptToResetResponseBeforeResolveException() throws UnsupportedEncodingException { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyControllerAdviceConfig.class); + this.resolver.setMappedHandlerClasses(HttpRequestHandler.class); + this.resolver.setApplicationContext(ctx); + this.resolver.afterPropertiesSet(); + + IllegalStateException ex = new IllegalStateException(); + ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); + MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); + mockHttpServletResponse.getWriter().print("test"); + ModelAndView mav = this.resolver.resolveException(this.request, mockHttpServletResponse, handler, ex); + + assertThat(mav).as("Exception was not handled").isNotNull(); + assertThat(mav.isEmpty()).isTrue(); + assertThat(mockHttpServletResponse.getContentAsString()).isEqualTo("DefaultTestExceptionResolver: IllegalStateException"); + } + private void assertMethodProcessorCount(int resolverCount, int handlerCount) { assertThat(this.resolver.getArgumentResolvers().getResolvers()).hasSize(resolverCount);