Fix issue with "redirect:" when a media type is present

Issue: SPR-15291
This commit is contained in:
Rossen Stoyanchev 2017-05-24 16:28:17 -04:00
parent 109746a03b
commit 718162b8c4
4 changed files with 45 additions and 7 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@ -169,6 +169,11 @@ public class RedirectView extends AbstractUrlBasedView {
}
@Override
public boolean isRedirectView() {
return true;
}
@Override
public boolean checkResourceExists(Locale locale) throws Exception {
return true;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@ -47,6 +47,13 @@ public interface View {
*/
List<MediaType> getSupportedMediaTypes();
/**
* Whether this View does rendering by performing a redirect.
*/
default boolean isRedirectView() {
return false;
}
/**
* Render the view based on the given {@link HandlerResult}. Implementations
* can access and use the model or only a specific attribute in it.

View File

@ -310,6 +310,12 @@ public class ViewResolutionResultHandler extends HandlerResultHandlerSupport
private Mono<? extends Void> render(List<View> views, Map<String, Object> model,
ServerWebExchange exchange) {
for (View view : views) {
if (view.isRedirectView()) {
return view.render(model, null, exchange);
}
}
List<MediaType> mediaTypes = getMediaTypes(views);
MediaType bestMediaType = selectMediaType(exchange, () -> mediaTypes);
if (bestMediaType != null) {

View File

@ -33,6 +33,7 @@ import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import rx.Completable;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
@ -42,6 +43,7 @@ import org.springframework.core.io.buffer.support.DataBufferTestUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
import org.springframework.mock.http.server.reactive.test.MockServerWebExchange;
import org.springframework.ui.ConcurrentModel;
import org.springframework.ui.Model;
@ -194,11 +196,10 @@ public class ViewResolutionResultHandlerTests {
@Test
public void handleWithMultipleResolvers() throws Exception {
Object returnValue = "profile";
MethodParameter returnType = on(Handler.class).annotNotPresent(ModelAttribute.class).resolveReturnType(String.class);
ViewResolver[] resolvers = {new TestViewResolver("account"), new TestViewResolver("profile")};
testHandle("/account", returnType, returnValue, "profile: {id=123}", resolvers);
testHandle("/account",
on(Handler.class).annotNotPresent(ModelAttribute.class).resolveReturnType(String.class),
"profile", "profile: {id=123}",
new TestViewResolver("account"), new TestViewResolver("profile"));
}
@Test
@ -280,6 +281,25 @@ public class ViewResolutionResultHandlerTests {
.verify();
}
@Test // SPR-15291
public void contentNegotiationWithRedirect() throws Exception {
HandlerResult handlerResult = new HandlerResult(new Object(), "redirect:/",
on(Handler.class).annotNotPresent(ModelAttribute.class).resolveReturnType(String.class),
this.bindingContext);
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
viewResolver.setApplicationContext(new StaticApplicationContext());
ViewResolutionResultHandler resultHandler = resultHandler(viewResolver);
MockServerWebExchange exchange = get("/account").accept(APPLICATION_JSON).toExchange();
resultHandler.handleResult(exchange, handlerResult).block(Duration.ZERO);
MockServerHttpResponse response = exchange.getResponse();
assertEquals(303, response.getStatusCode().value());
assertEquals("/", response.getHeaders().getLocation().toString());
}
private ViewResolutionResultHandler resultHandler(ViewResolver... resolvers) {
return resultHandler(Collections.emptyList(), resolvers);