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:
@@ -27,7 +27,11 @@ import org.springframework.cloud.function.web.RequestProcessor.FunctionWrapper;
|
||||
import org.springframework.cloud.function.web.constants.WebRequestConstants;
|
||||
import org.springframework.http.MediaType;
|
||||
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.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@@ -49,13 +53,34 @@ public class FunctionController {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@PostMapping(path = "/**", consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
MediaType.MULTIPART_FORM_DATA_VALUE })
|
||||
@PostMapping(path = "/**", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
@ResponseBody
|
||||
public Mono<ResponseEntity<?>> form(ServerWebExchange request) {
|
||||
FunctionWrapper wrapper = wrapper(request);
|
||||
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 = "/**")
|
||||
|
||||
@@ -302,7 +302,6 @@ public class HttpPostIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void multipart() throws Exception {
|
||||
|
||||
LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
||||
|
||||
@@ -307,6 +307,20 @@ public class HttpPostIntegrationTests {
|
||||
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
|
||||
public void count() throws Exception {
|
||||
List<String> list = Arrays.asList("A", "B", "A");
|
||||
|
||||
Reference in New Issue
Block a user