diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java index b643c4fe17..75567f0f1a 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java @@ -49,6 +49,7 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.core.log.LogFormatUtils; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.server.RequestPath; import org.springframework.http.server.ServletServerHttpRequest; @@ -1208,9 +1209,10 @@ public class DispatcherServlet extends FrameworkServlet { // Success and error responses may use different content types request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); - // Reset the response body buffer if the response is not committed already, - // leaving the response headers in place. + // Reset the response content-type header and body buffer if the response is not committed already, + // leaving the other response headers in place. try { + response.setHeader(HttpHeaders.CONTENT_TYPE, null); response.resetBuffer(); } catch (IllegalStateException illegalStateException) { diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java index 9a52bf640c..21c3efa4a8 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java @@ -898,6 +898,23 @@ class DispatcherServletTests { assertThat(response.getHeader("Test-Header")).isEqualTo("spring"); } + @Test + void shouldResetContentTypeIfNotCommitted() throws Exception { + StaticWebApplicationContext context = new StaticWebApplicationContext(); + context.setServletContext(getServletContext()); + context.registerSingleton("/error", ErrorController.class); + DispatcherServlet servlet = new DispatcherServlet(context); + servlet.init(servletConfig); + + MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/error"); + MockHttpServletResponse response = new MockHttpServletResponse(); + assertThatThrownBy(() -> servlet.service(request, response)).isInstanceOf(ServletException.class) + .hasCauseInstanceOf(IllegalArgumentException.class); + assertThat(response.getContentAsByteArray()).isEmpty(); + assertThat(response.getStatus()).isEqualTo(400); + assertThat(response.getHeaderNames()).doesNotContain(HttpHeaders.CONTENT_TYPE); + } + public static class ControllerFromParent implements Controller { @@ -950,6 +967,7 @@ class DispatcherServletTests { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { response.setStatus(400); response.setHeader("Test-Header", "spring"); + response.addHeader("Content-Type", "application/json"); if (request.getAttribute("commit") != null) { response.flushBuffer(); }