diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java index ce9d1f92e0..51bbcfd559 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Consumer; @@ -177,7 +178,7 @@ class DefaultRenderingResponseBuilder implements RenderingResponse.Builder { public Mono writeTo(ServerWebExchange exchange, Context context) { ServerHttpResponse response = exchange.getResponse(); writeStatusAndHeaders(response); - MediaType contentType = exchange.getResponse().getHeaders().getContentType(); + MediaType responseContentType = exchange.getResponse().getHeaders().getContentType(); Locale locale = LocaleContextHolder.getLocale(exchange.getLocaleContext()); Stream viewResolverStream = context.viewResolvers().stream(); @@ -186,7 +187,11 @@ class DefaultRenderingResponseBuilder implements RenderingResponse.Builder { .next() .switchIfEmpty(Mono.error(new IllegalArgumentException("Could not resolve view with name '" + name() +"'"))) - .flatMap(view -> view.render(model(), contentType, exchange)); + .flatMap(view -> { + List mediaTypes = view.getSupportedMediaTypes(); + MediaType contentType = (responseContentType == null && !mediaTypes.isEmpty() ? mediaTypes.get(0) : responseContentType); + return view.render(model(), contentType, exchange); + }); } } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseTests.java index 801d67a46c..b664a8b4b8 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseTests.java @@ -28,14 +28,19 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.web.test.server.MockServerWebExchange; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.result.view.AbstractView; import org.springframework.web.reactive.result.view.View; import org.springframework.web.reactive.result.view.ViewResolver; +import org.springframework.web.reactive.result.view.ViewResolverSupport; +import org.springframework.web.server.ServerWebExchange; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.*; /** @@ -143,4 +148,37 @@ public class DefaultRenderingResponseTests { .verify(); } + @Test + public void defaultContentType() throws Exception { + Mono result = RenderingResponse.create("view").build(); + + MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("http://localhost")); + TestView view = new TestView(); + ViewResolver viewResolver = mock(ViewResolver.class); + when(viewResolver.resolveViewName(any(), any())).thenReturn(Mono.just(view)); + + List viewResolvers = new ArrayList<>(); + viewResolvers.add(viewResolver); + + ServerResponse.Context context = mock(ServerResponse.Context.class); + when(context.viewResolvers()).thenReturn(viewResolvers); + + StepVerifier.create(result.flatMap(response -> response.writeTo(exchange, context))) + .verifyComplete(); + + assertEquals(ViewResolverSupport.DEFAULT_CONTENT_TYPE, exchange.getResponse().getHeaders().getContentType()); + } + + + private static class TestView extends AbstractView { + + @Override + protected Mono renderInternal(Map renderAttributes, + MediaType contentType, ServerWebExchange exchange) { + + return Mono.empty(); + } + + } + }