Deprecate ignoreDefaultModelOnRedirect property

Closes gh-28324
This commit is contained in:
rstoyanchev
2022-09-14 18:13:38 +01:00
parent 250880bf90
commit f3c082abac
10 changed files with 82 additions and 217 deletions

View File

@@ -34,10 +34,8 @@ import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.http.client.MultipartBodyBuilder;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.reactive.server.EntityExchangeResult;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.client.MockMvcWebTestClient;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -46,7 +44,6 @@ import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.multipart.MultipartFile;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
/**
* {@link MockMvcWebTestClient} equivalent of the MockMvc
@@ -69,28 +66,18 @@ public class MultipartControllerTests {
bodyBuilder.part("file", fileContent).filename("orig");
bodyBuilder.part("json", json, MediaType.APPLICATION_JSON);
EntityExchangeResult<Void> exchangeResult = testClient.post().uri("/multipartfile")
testClient.post().uri("/multipartfile")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", json));
// Now try the same with HTTP PUT
exchangeResult = testClient.put().uri("/multipartfile-via-put")
testClient.put().uri("/multipartfile-via-put")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", json));
}
@Test
@@ -110,16 +97,11 @@ public class MultipartControllerTests {
bodyBuilder.part("file", fileContent).filename("orig");
bodyBuilder.part("json", json, MediaType.APPLICATION_JSON);
EntityExchangeResult<Void> exchangeResult = testClient.post().uri("/multipartfilearray")
testClient.post().uri("/multipartfilearray")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", json));
}
@Test
@@ -138,16 +120,11 @@ public class MultipartControllerTests {
bodyBuilder.part("file", fileContent).filename("orig");
bodyBuilder.part("json", json, MediaType.APPLICATION_JSON);
EntityExchangeResult<Void> exchangeResult = testClient.post().uri("/optionalfile")
testClient.post().uri("/optionalfile")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", json));
}
@Test
@@ -157,16 +134,11 @@ public class MultipartControllerTests {
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
bodyBuilder.part("json", json, MediaType.APPLICATION_JSON);
EntityExchangeResult<Void> exchangeResult = testClient.post().uri("/optionalfile")
testClient.post().uri("/optionalfile")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attributeDoesNotExist("fileContent"))
.andExpect(model().attribute("jsonContent", json));
}
@Test
@@ -179,16 +151,11 @@ public class MultipartControllerTests {
bodyBuilder.part("file", fileContent).filename("orig");
bodyBuilder.part("json", json, MediaType.APPLICATION_JSON);
EntityExchangeResult<Void> exchangeResult = testClient.post().uri("/optionalfilearray")
testClient.post().uri("/optionalfilearray")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", json));
}
@Test
@@ -198,16 +165,11 @@ public class MultipartControllerTests {
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
bodyBuilder.part("json", json, MediaType.APPLICATION_JSON);
EntityExchangeResult<Void> exchangeResult = testClient.post().uri("/optionalfilearray")
testClient.post().uri("/optionalfilearray")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attributeDoesNotExist("fileContent"))
.andExpect(model().attribute("jsonContent", json));
}
@Test
@@ -220,16 +182,11 @@ public class MultipartControllerTests {
bodyBuilder.part("file", fileContent).filename("orig");
bodyBuilder.part("json", json, MediaType.APPLICATION_JSON);
EntityExchangeResult<Void> exchangeResult = testClient.post().uri("/optionalfilelist")
testClient.post().uri("/optionalfilelist")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", json));
}
@Test
@@ -239,16 +196,11 @@ public class MultipartControllerTests {
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
bodyBuilder.part("json", json, MediaType.APPLICATION_JSON);
EntityExchangeResult<Void> exchangeResult = testClient.post().uri("/optionalfilelist")
testClient.post().uri("/optionalfilelist")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attributeDoesNotExist("fileContent"))
.andExpect(model().attribute("jsonContent", json));
}
@Test
@@ -260,16 +212,11 @@ public class MultipartControllerTests {
bodyBuilder.part("file", fileContent).filename("orig");
bodyBuilder.part("json", json, MediaType.APPLICATION_JSON);
EntityExchangeResult<Void> exchangeResult = testClient.post().uri("/multipartfile")
testClient.post().uri("/multipartfile")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", json));
}
@Test
@@ -283,15 +230,11 @@ public class MultipartControllerTests {
.filter(new RequestWrappingFilter())
.build();
EntityExchangeResult<Void> exchangeResult = client.post().uri("/multipartfile")
client.post().uri("/multipartfile")
.bodyValue(bodyBuilder.build())
.exchange()
.expectStatus().isFound()
.expectBody().isEmpty();
// Further assertions on the server response
MockMvcWebTestClient.resultActionsFor(exchangeResult)
.andExpect(model().attribute("jsonContent", json));
}
@@ -301,110 +244,78 @@ public class MultipartControllerTests {
@PostMapping("/multipartfile")
public String processMultipartFile(@RequestParam(required = false) MultipartFile file,
@RequestPart(required = false) Map<String, String> json, Model model) throws IOException {
if (file != null) {
model.addAttribute("fileContent", file.getBytes());
}
if (json != null) {
model.addAttribute("jsonContent", json);
}
@RequestPart(required = false) Map<String, String> json) {
return "redirect:/index";
}
@PutMapping("/multipartfile-via-put")
public String processMultipartFileViaHttpPut(@RequestParam(required = false) MultipartFile file,
@RequestPart(required = false) Map<String, String> json, Model model) throws IOException {
@RequestPart(required = false) Map<String, String> json) {
return processMultipartFile(file, json, model);
return processMultipartFile(file, json);
}
@PostMapping("/multipartfilearray")
public String processMultipartFileArray(@RequestParam(required = false) MultipartFile[] file,
@RequestPart(required = false) Map<String, String> json, Model model) throws IOException {
@RequestPart(required = false) Map<String, String> json) throws IOException {
if (file != null && file.length > 0) {
byte[] content = file[0].getBytes();
assertThat(file[1].getBytes()).isEqualTo(content);
model.addAttribute("fileContent", content);
}
if (json != null) {
model.addAttribute("jsonContent", json);
}
return "redirect:/index";
}
@PostMapping("/multipartfilelist")
public String processMultipartFileList(@RequestParam(required = false) List<MultipartFile> file,
@RequestPart(required = false) Map<String, String> json, Model model) throws IOException {
@RequestPart(required = false) Map<String, String> json) throws IOException {
if (file != null && !file.isEmpty()) {
byte[] content = file.get(0).getBytes();
assertThat(file.get(1).getBytes()).isEqualTo(content);
model.addAttribute("fileContent", content);
}
if (json != null) {
model.addAttribute("jsonContent", json);
}
return "redirect:/index";
}
@PostMapping("/optionalfile")
public String processOptionalFile(@RequestParam Optional<MultipartFile> file,
@RequestPart Map<String, String> json, Model model) throws IOException {
if (file.isPresent()) {
model.addAttribute("fileContent", file.get().getBytes());
}
model.addAttribute("jsonContent", json);
public String processOptionalFile(
@RequestParam Optional<MultipartFile> file, @RequestPart Map<String, String> json) {
return "redirect:/index";
}
@PostMapping("/optionalfilearray")
public String processOptionalFileArray(@RequestParam Optional<MultipartFile[]> file,
@RequestPart Map<String, String> json, Model model) throws IOException {
public String processOptionalFileArray(
@RequestParam Optional<MultipartFile[]> file, @RequestPart Map<String, String> json)
throws IOException {
if (file.isPresent()) {
byte[] content = file.get()[0].getBytes();
assertThat(file.get()[1].getBytes()).isEqualTo(content);
model.addAttribute("fileContent", content);
}
model.addAttribute("jsonContent", json);
return "redirect:/index";
}
@PostMapping("/optionalfilelist")
public String processOptionalFileList(@RequestParam Optional<List<MultipartFile>> file,
@RequestPart Map<String, String> json, Model model) throws IOException {
public String processOptionalFileList(
@RequestParam Optional<List<MultipartFile>> file, @RequestPart Map<String, String> json)
throws IOException {
if (file.isPresent()) {
byte[] content = file.get().get(0).getBytes();
assertThat(file.get().get(1).getBytes()).isEqualTo(content);
model.addAttribute("fileContent", content);
}
model.addAttribute("jsonContent", json);
return "redirect:/index";
}
@PostMapping("/part")
public String processPart(@RequestParam Part part,
@RequestPart Map<String, String> json, Model model) throws IOException {
model.addAttribute("fileContent", part.getInputStream());
model.addAttribute("jsonContent", json);
public String processPart(@RequestParam Part part, @RequestPart Map<String, String> json) {
return "redirect:/index";
}
@PostMapping("/json")
public String processMultipart(@RequestPart Map<String, String> json, Model model) {
model.addAttribute("json", json);
public String processMultipart(@RequestPart Map<String, String> json) {
return "redirect:/index";
}
}

View File

@@ -40,8 +40,6 @@ import org.springframework.mock.web.MockPart;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
import org.springframework.ui.Model;
import org.springframework.util.StreamUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
@@ -49,11 +47,11 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@@ -88,9 +86,7 @@ class MultipartControllerTests {
standaloneSetup(new MultipartController()).build()
.perform(requestBuilder.file(jsonPart))
.andExpect(status().isFound())
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", Collections.singletonMap("name", "yeeeah")));
.andExpect(status().isFound());
}
@Test
@@ -111,9 +107,7 @@ class MultipartControllerTests {
standaloneSetup(new MultipartController()).build()
.perform(multipart("/multipartfilearray").file(filePart1).file(filePart2).file(jsonPart))
.andExpect(status().isFound())
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", Collections.singletonMap("name", "yeeeah")));
.andExpect(status().isFound());
}
@Test
@@ -141,9 +135,7 @@ class MultipartControllerTests {
standaloneSetup(new MultipartController()).build()
.perform(multipart("/multipartfilelist").file(filePart1).file(filePart2).file(jsonPart))
.andExpect(status().isFound())
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", Collections.singletonMap("name", "yeeeah")));
.andExpect(status().isFound());
}
@Test
@@ -170,9 +162,7 @@ class MultipartControllerTests {
standaloneSetup(new MultipartController()).build()
.perform(multipart("/optionalfile").file(filePart).file(jsonPart))
.andExpect(status().isFound())
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", Collections.singletonMap("name", "yeeeah")));
.andExpect(status().isFound());
}
@Test
@@ -182,9 +172,7 @@ class MultipartControllerTests {
standaloneSetup(new MultipartController()).build()
.perform(multipart("/optionalfile").file(jsonPart))
.andExpect(status().isFound())
.andExpect(model().attributeDoesNotExist("fileContent"))
.andExpect(model().attribute("jsonContent", Collections.singletonMap("name", "yeeeah")));
.andExpect(status().isFound());
}
@Test
@@ -198,9 +186,7 @@ class MultipartControllerTests {
standaloneSetup(new MultipartController()).build()
.perform(multipart("/optionalfilearray").file(filePart1).file(filePart2).file(jsonPart))
.andExpect(status().isFound())
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", Collections.singletonMap("name", "yeeeah")));
.andExpect(status().isFound());
}
@Test
@@ -210,9 +196,7 @@ class MultipartControllerTests {
standaloneSetup(new MultipartController()).build()
.perform(multipart("/optionalfilearray").file(jsonPart))
.andExpect(status().isFound())
.andExpect(model().attributeDoesNotExist("fileContent"))
.andExpect(model().attribute("jsonContent", Collections.singletonMap("name", "yeeeah")));
.andExpect(status().isFound());
}
@Test
@@ -226,9 +210,7 @@ class MultipartControllerTests {
standaloneSetup(new MultipartController()).build()
.perform(multipart("/optionalfilelist").file(filePart1).file(filePart2).file(jsonPart))
.andExpect(status().isFound())
.andExpect(model().attribute("fileContent", fileContent))
.andExpect(model().attribute("jsonContent", Collections.singletonMap("name", "yeeeah")));
.andExpect(status().isFound());
}
@Test
@@ -238,9 +220,7 @@ class MultipartControllerTests {
standaloneSetup(new MultipartController()).build()
.perform(multipart("/optionalfilelist").file(jsonPart))
.andExpect(status().isFound())
.andExpect(model().attributeDoesNotExist("fileContent"))
.andExpect(model().attribute("jsonContent", Collections.singletonMap("name", "yeeeah")));
.andExpect(status().isFound());
}
@Test
@@ -250,8 +230,7 @@ class MultipartControllerTests {
standaloneSetup(new MultipartController()).build()
.perform(multipart("/multipartfilebinding").part(filePart))
.andExpect(status().isFound())
.andExpect(model().attribute("fileContent", fileContent));
.andExpect(status().isFound());
}
@Test // SPR-13317
@@ -263,128 +242,96 @@ class MultipartControllerTests {
MockMvc mockMvc = standaloneSetup(new MultipartController()).addFilter(filter).build();
Map<String, String> jsonMap = Collections.singletonMap("name", "yeeeah");
mockMvc.perform(multipart("/json").file(jsonPart)).andExpect(model().attribute("json", jsonMap));
mockMvc.perform(multipart("/json").file(jsonPart)).andExpect(status().isFound());
}
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Controller
private static class MultipartController {
@PostMapping("/multipartfile")
public String processMultipartFile(@RequestParam(required = false) MultipartFile file,
@RequestPart(required = false) Map<String, String> json, Model model) throws IOException {
if (file != null) {
model.addAttribute("fileContent", file.getBytes());
}
if (json != null) {
model.addAttribute("jsonContent", json);
}
@RequestPart(required = false) Map<String, String> json) throws IOException {
return "redirect:/index";
}
@PutMapping("/multipartfile-via-put")
public String processMultipartFileViaHttpPut(@RequestParam(required = false) MultipartFile file,
@RequestPart(required = false) Map<String, String> json, Model model) throws IOException {
@RequestPart(required = false) Map<String, String> json) throws IOException {
return processMultipartFile(file, json, model);
return processMultipartFile(file, json);
}
@PostMapping("/multipartfilearray")
public String processMultipartFileArray(@RequestParam(required = false) MultipartFile[] file,
@RequestPart(required = false) Map<String, String> json, Model model) throws IOException {
@RequestPart(required = false) Map<String, String> json) throws IOException {
if (file != null && file.length > 0) {
byte[] content = file[0].getBytes();
assertThat(file[1].getBytes()).isEqualTo(content);
model.addAttribute("fileContent", content);
}
if (json != null) {
model.addAttribute("jsonContent", json);
}
return "redirect:/index";
}
@PostMapping("/multipartfilelist")
public String processMultipartFileList(@RequestParam(required = false) List<MultipartFile> file,
@RequestPart(required = false) Map<String, String> json, Model model) throws IOException {
@RequestPart(required = false) Map<String, String> json) throws IOException {
if (file != null && !file.isEmpty()) {
byte[] content = file.get(0).getBytes();
assertThat(file.get(1).getBytes()).isEqualTo(content);
model.addAttribute("fileContent", content);
}
if (json != null) {
model.addAttribute("jsonContent", json);
}
return "redirect:/index";
}
@PostMapping("/optionalfile")
public String processOptionalFile(@RequestParam Optional<MultipartFile> file,
@RequestPart Map<String, String> json, Model model) throws IOException {
if (file.isPresent()) {
model.addAttribute("fileContent", file.get().getBytes());
}
model.addAttribute("jsonContent", json);
public String processOptionalFile(
@RequestParam Optional<MultipartFile> file, @RequestPart Map<String, String> json) {
return "redirect:/index";
}
@PostMapping("/optionalfilearray")
public String processOptionalFileArray(@RequestParam Optional<MultipartFile[]> file,
@RequestPart Map<String, String> json, Model model) throws IOException {
public String processOptionalFileArray(
@RequestParam Optional<MultipartFile[]> file, @RequestPart Map<String, String> json)
throws IOException {
if (file.isPresent()) {
byte[] content = file.get()[0].getBytes();
assertThat(file.get()[1].getBytes()).isEqualTo(content);
model.addAttribute("fileContent", content);
}
model.addAttribute("jsonContent", json);
return "redirect:/index";
}
@PostMapping("/optionalfilelist")
public String processOptionalFileList(@RequestParam Optional<List<MultipartFile>> file,
@RequestPart Map<String, String> json, Model model) throws IOException {
public String processOptionalFileList(
@RequestParam Optional<List<MultipartFile>> file, @RequestPart Map<String, String> json)
throws IOException {
if (file.isPresent()) {
byte[] content = file.get().get(0).getBytes();
assertThat(file.get().get(1).getBytes()).isEqualTo(content);
model.addAttribute("fileContent", content);
}
model.addAttribute("jsonContent", json);
return "redirect:/index";
}
@PostMapping("/part")
public String processPart(@RequestPart Part part,
@RequestPart Map<String, String> json, Model model) throws IOException {
if (part != null) {
byte[] content = StreamUtils.copyToByteArray(part.getInputStream());
model.addAttribute("fileContent", content);
}
model.addAttribute("jsonContent", json);
public String processPart(@RequestPart Part part, @RequestPart Map<String, String> json) {
return "redirect:/index";
}
@PostMapping("/json")
public String processMultipart(@RequestPart Map<String, String> json, Model model) {
model.addAttribute("json", json);
public String processMultipart(@RequestPart Map<String, String> json) {
return "redirect:/index";
}
@PostMapping("/multipartfilebinding")
public String processMultipartFileBean(
MultipartFileBean multipartFileBean, Model model, BindingResult bindingResult) throws IOException {
MultipartFileBean multipartFileBean, RedirectAttributes model, BindingResult bindingResult)
throws IOException {
if (!bindingResult.hasErrors()) {
MultipartFile file = multipartFileBean.getFile();
@@ -396,6 +343,7 @@ class MultipartControllerTests {
}
}
private static class MultipartFileBean {
private MultipartFile file;
@@ -414,8 +362,9 @@ class MultipartControllerTests {
private static class RequestWrappingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
request = new HttpServletRequestWrapper(request);
filterChain.doFilter(request, response);