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 243148ee1efd..7b2c44271968 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,6 +48,7 @@ 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.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.server.RequestPath; @@ -1341,9 +1342,10 @@ protected ModelAndView processHandlerException(HttpServletRequest request, HttpS // 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 65867661a495..bebbc9f2f1ea 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -924,6 +924,23 @@ void shouldAttemptToResetResponseBufferIfCommitted() throws Exception { 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 { @@ -976,6 +993,7 @@ private static class ErrorController implements Controller { 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(); }