Set default view content-type with WebFlux fn
With this commit, the default content-type defined by the view (usually "text/html;charset=UTF-8" defined in AbstractView) is used if any, when none is defined in the response headers. Issue: SPR-16247
This commit is contained in:
parent
e3e4f37222
commit
99cbfd32c3
|
@ -20,6 +20,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -177,7 +178,7 @@ class DefaultRenderingResponseBuilder implements RenderingResponse.Builder {
|
||||||
public Mono<Void> writeTo(ServerWebExchange exchange, Context context) {
|
public Mono<Void> writeTo(ServerWebExchange exchange, Context context) {
|
||||||
ServerHttpResponse response = exchange.getResponse();
|
ServerHttpResponse response = exchange.getResponse();
|
||||||
writeStatusAndHeaders(response);
|
writeStatusAndHeaders(response);
|
||||||
MediaType contentType = exchange.getResponse().getHeaders().getContentType();
|
MediaType responseContentType = exchange.getResponse().getHeaders().getContentType();
|
||||||
Locale locale = LocaleContextHolder.getLocale(exchange.getLocaleContext());
|
Locale locale = LocaleContextHolder.getLocale(exchange.getLocaleContext());
|
||||||
Stream<ViewResolver> viewResolverStream = context.viewResolvers().stream();
|
Stream<ViewResolver> viewResolverStream = context.viewResolvers().stream();
|
||||||
|
|
||||||
|
@ -186,7 +187,11 @@ class DefaultRenderingResponseBuilder implements RenderingResponse.Builder {
|
||||||
.next()
|
.next()
|
||||||
.switchIfEmpty(Mono.error(new IllegalArgumentException("Could not resolve view with name '" +
|
.switchIfEmpty(Mono.error(new IllegalArgumentException("Could not resolve view with name '" +
|
||||||
name() +"'")))
|
name() +"'")))
|
||||||
.flatMap(view -> view.render(model(), contentType, exchange));
|
.flatMap(view -> {
|
||||||
|
List<MediaType> mediaTypes = view.getSupportedMediaTypes();
|
||||||
|
MediaType contentType = (responseContentType == null && !mediaTypes.isEmpty() ? mediaTypes.get(0) : responseContentType);
|
||||||
|
return view.render(model(), contentType, exchange);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,14 +28,19 @@ import reactor.core.publisher.Mono;
|
||||||
import reactor.test.StepVerifier;
|
import reactor.test.StepVerifier;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseCookie;
|
import org.springframework.http.ResponseCookie;
|
||||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||||
import org.springframework.mock.web.test.server.MockServerWebExchange;
|
import org.springframework.mock.web.test.server.MockServerWebExchange;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
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.View;
|
||||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
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.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -143,4 +148,37 @@ public class DefaultRenderingResponseTests {
|
||||||
.verify();
|
.verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defaultContentType() throws Exception {
|
||||||
|
Mono<RenderingResponse> 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<ViewResolver> 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<Void> renderInternal(Map<String, Object> renderAttributes,
|
||||||
|
MediaType contentType, ServerWebExchange exchange) {
|
||||||
|
|
||||||
|
return Mono.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue