Fix multi-part form handling for WebFlux apps
In WebFlux (but not MVC) you have to explicitly ask for the multi- part content separately from the form data. Fixes gh-223
This commit is contained in:
@@ -92,7 +92,7 @@ public class SampleApplicationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
// @Ignore
|
||||||
public void multipart() throws Exception {
|
public void multipart() throws Exception {
|
||||||
|
|
||||||
LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
||||||
|
|||||||
@@ -27,7 +27,11 @@ import org.springframework.cloud.function.web.RequestProcessor.FunctionWrapper;
|
|||||||
import org.springframework.cloud.function.web.constants.WebRequestConstants;
|
import org.springframework.cloud.function.web.constants.WebRequestConstants;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.http.codec.multipart.FormFieldPart;
|
||||||
|
import org.springframework.http.codec.multipart.Part;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
@@ -49,13 +53,34 @@ public class FunctionController {
|
|||||||
this.processor = processor;
|
this.processor = processor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(path = "/**", consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
@PostMapping(path = "/**", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
MediaType.MULTIPART_FORM_DATA_VALUE })
|
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Mono<ResponseEntity<?>> form(ServerWebExchange request) {
|
public Mono<ResponseEntity<?>> form(ServerWebExchange request) {
|
||||||
FunctionWrapper wrapper = wrapper(request);
|
FunctionWrapper wrapper = wrapper(request);
|
||||||
return request.getFormData().doOnSuccess(params -> wrapper.params(params))
|
return request.getFormData().doOnSuccess(params -> wrapper.params(params))
|
||||||
.then(processor.post(wrapper, null, false));
|
.then(Mono.defer(() -> processor.post(wrapper, null, false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(path = "/**", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||||
|
@ResponseBody
|
||||||
|
public Mono<ResponseEntity<?>> multipart(ServerWebExchange request) {
|
||||||
|
FunctionWrapper wrapper = wrapper(request);
|
||||||
|
return request.getMultipartData()
|
||||||
|
.doOnSuccess(params -> wrapper.params(multi(params)))
|
||||||
|
.then(Mono.defer(() -> processor.post(wrapper, null, false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private MultiValueMap<String, String> multi(MultiValueMap<String, Part> body) {
|
||||||
|
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
||||||
|
for (String key : body.keySet()) {
|
||||||
|
for (Part part : body.get(key)) {
|
||||||
|
if (part instanceof FormFieldPart) {
|
||||||
|
FormFieldPart form = (FormFieldPart) part;
|
||||||
|
map.add(key, form.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(path = "/**")
|
@PostMapping(path = "/**")
|
||||||
|
|||||||
@@ -302,7 +302,6 @@ public class HttpPostIntegrationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
|
||||||
public void multipart() throws Exception {
|
public void multipart() throws Exception {
|
||||||
|
|
||||||
LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
||||||
|
|||||||
@@ -307,6 +307,20 @@ public class HttpPostIntegrationTests {
|
|||||||
String.class).getBody()).isEqualTo("[{\"A\":6,\"B\":11}]");
|
String.class).getBody()).isEqualTo("[{\"A\":6,\"B\":11}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multipart() throws Exception {
|
||||||
|
|
||||||
|
LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
||||||
|
|
||||||
|
map.put("A", Arrays.asList("1", "2", "3"));
|
||||||
|
map.put("B", Arrays.asList("5", "6"));
|
||||||
|
|
||||||
|
assertThat(rest.exchange(
|
||||||
|
RequestEntity.post(new URI("/sum")).accept(MediaType.APPLICATION_JSON)
|
||||||
|
.contentType(MediaType.MULTIPART_FORM_DATA).body(map),
|
||||||
|
String.class).getBody()).isEqualTo("[{\"A\":6,\"B\":11}]");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void count() throws Exception {
|
public void count() throws Exception {
|
||||||
List<String> list = Arrays.asList("A", "B", "A");
|
List<String> list = Arrays.asList("A", "B", "A");
|
||||||
|
|||||||
Reference in New Issue
Block a user