Move status/header handling into FragmentsRendering
Based on feedback from htmx-spring-boot. It's more generally useful to process those from within DefaultFragmentsRendering rather than in ModelAndViewMethodReturnValueHandler. That way a custom return value handler can create a FragmentsRendering as well and get the same result. See gh-33194
This commit is contained in:
@@ -18,12 +18,8 @@ package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||
@@ -100,13 +96,6 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
|
||||
}
|
||||
|
||||
if (returnValue instanceof FragmentsRendering rendering) {
|
||||
mavContainer.setStatus(rendering.status());
|
||||
HttpHeaders headers = rendering.headers();
|
||||
if (!headers.isEmpty()) {
|
||||
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
|
||||
Assert.state(response != null, "No HttpServletResponse");
|
||||
headers.forEach((name, values) -> values.forEach(value -> response.addHeader(name, value)));
|
||||
}
|
||||
mavContainer.setView(rendering);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -101,6 +101,14 @@ final class DefaultFragmentsRendering implements FragmentsRendering {
|
||||
@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
|
||||
throws Exception {
|
||||
|
||||
if (this.status != null) {
|
||||
response.setStatus(this.status.value());
|
||||
}
|
||||
|
||||
if (!this.headers.isEmpty()) {
|
||||
this.headers.forEach((name, values) -> values.forEach(value -> response.addHeader(name, value)));
|
||||
}
|
||||
|
||||
if (model != null) {
|
||||
model.forEach((key, value) ->
|
||||
this.modelAndViews.forEach(mv -> mv.getModel().putIfAbsent(key, value)));
|
||||
|
||||
@@ -91,13 +91,10 @@ class ModelAndViewMethodReturnValueHandlerTests {
|
||||
|
||||
@Test
|
||||
void handleFragmentsRendering() throws Exception {
|
||||
FragmentsRendering rendering = FragmentsRendering.with("viewName")
|
||||
.header("headerName", "headerValue")
|
||||
.build();
|
||||
FragmentsRendering rendering = FragmentsRendering.with("viewName").build();
|
||||
|
||||
handler.handleReturnValue(rendering, returnParamModelAndView, mavContainer, webRequest);
|
||||
assertThat(mavContainer.getView()).isInstanceOf(SmartView.class);
|
||||
assertThat(this.webRequest.getResponse().getHeader("headerName")).isEqualTo("headerValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -43,7 +43,6 @@ import static org.junit.jupiter.api.condition.JRE.JAVA_21;
|
||||
@DisabledForJreRange(min = JAVA_21, disabledReason = "Kotlin doesn't support Java 21+ yet")
|
||||
public class DefaultFragmentsRenderingTests {
|
||||
|
||||
|
||||
@Test
|
||||
void render() throws Exception {
|
||||
|
||||
@@ -59,11 +58,13 @@ public class DefaultFragmentsRenderingTests {
|
||||
|
||||
FragmentsRendering view = FragmentsRendering.with("fragment1", Map.of("foo", "Foo"))
|
||||
.fragment("fragment2", Map.of("bar", "Bar"))
|
||||
.header("headerName", "headerValue")
|
||||
.build();
|
||||
|
||||
view.resolveNestedViews(viewResolver, Locale.ENGLISH);
|
||||
view.render(Collections.emptyMap(), request, response);
|
||||
|
||||
assertThat(response.getHeader("headerName")).isEqualTo("headerValue");
|
||||
assertThat(response.getContentAsString()).isEqualTo("""
|
||||
<p>
|
||||
Hello Foo
|
||||
|
||||
Reference in New Issue
Block a user