WebFlux @RequestPart support for List and Flux arguments
The resolver now supports List<T>, Flux<T>, and List<Part>. Issue: SPR-16621
This commit is contained in:
@@ -74,35 +74,49 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageReaderArgu
|
||||
boolean isRequired = (requestPart == null || requestPart.required());
|
||||
String name = getPartName(parameter, requestPart);
|
||||
|
||||
Flux<Part> values = exchange.getMultipartData()
|
||||
Flux<Part> parts = exchange.getMultipartData()
|
||||
.flatMapMany(map -> {
|
||||
List<Part> parts = map.get(name);
|
||||
if (CollectionUtils.isEmpty(parts)) {
|
||||
List<Part> list = map.get(name);
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return isRequired ?
|
||||
Flux.error(getMissingPartException(name, parameter)) :
|
||||
Flux.empty();
|
||||
}
|
||||
return Flux.fromIterable(parts);
|
||||
return Flux.fromIterable(list);
|
||||
});
|
||||
|
||||
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(parameter.getParameterType());
|
||||
MethodParameter elementType = adapter != null ? parameter.nested() : parameter;
|
||||
if (Part.class.isAssignableFrom(parameter.getParameterType())) {
|
||||
return parts.next().cast(Object.class);
|
||||
}
|
||||
|
||||
if (Part.class.isAssignableFrom(elementType.getNestedParameterType())) {
|
||||
if (adapter != null) {
|
||||
values = adapter.isMultiValue() ? values : values.take(1);
|
||||
return Mono.just(adapter.fromPublisher(values));
|
||||
if (List.class.isAssignableFrom(parameter.getParameterType())) {
|
||||
MethodParameter elementType = parameter.nested();
|
||||
if (Part.class.isAssignableFrom(elementType.getNestedParameterType())) {
|
||||
return parts.collectList().cast(Object.class);
|
||||
}
|
||||
else {
|
||||
return values.next().cast(Object.class);
|
||||
return decodePartValues(parts, elementType, bindingContext, exchange, isRequired)
|
||||
.collectList().cast(Object.class);
|
||||
}
|
||||
}
|
||||
|
||||
return values.next().flatMap(part -> {
|
||||
ServerHttpRequest partRequest = new PartServerHttpRequest(exchange.getRequest(), part);
|
||||
ServerWebExchange partExchange = exchange.mutate().request(partRequest).build();
|
||||
return readBody(parameter, isRequired, bindingContext, partExchange);
|
||||
});
|
||||
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(parameter.getParameterType());
|
||||
if (adapter != null) {
|
||||
// Mono<Part> or Flux<Part>
|
||||
MethodParameter elementType = parameter.nested();
|
||||
if (Part.class.isAssignableFrom(elementType.getNestedParameterType())) {
|
||||
parts = adapter.isMultiValue() ? parts : parts.take(1);
|
||||
return Mono.just(adapter.fromPublisher(parts));
|
||||
}
|
||||
// We have to decode the content for each part, one at a time
|
||||
if (adapter.isMultiValue()) {
|
||||
return Mono.just(decodePartValues(parts, elementType, bindingContext, exchange, isRequired));
|
||||
}
|
||||
}
|
||||
|
||||
// <T> or Mono<T>
|
||||
return decodePartValues(parts, parameter, bindingContext, exchange, isRequired)
|
||||
.next().cast(Object.class);
|
||||
}
|
||||
|
||||
private String getPartName(MethodParameter methodParam, @Nullable RequestPart requestPart) {
|
||||
@@ -124,6 +138,17 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageReaderArgu
|
||||
}
|
||||
|
||||
|
||||
private Flux<?> decodePartValues(Flux<Part> parts, MethodParameter elementType, BindingContext bindingContext,
|
||||
ServerWebExchange exchange, boolean isRequired) {
|
||||
|
||||
return parts.flatMap(part -> {
|
||||
ServerHttpRequest partRequest = new PartServerHttpRequest(exchange.getRequest(), part);
|
||||
ServerWebExchange partExchange = exchange.mutate().request(partRequest).build();
|
||||
return readBody(elementType, isRequired, bindingContext, partExchange);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static class PartServerHttpRequest extends ServerHttpRequestDecorator {
|
||||
|
||||
private final Part part;
|
||||
|
||||
Reference in New Issue
Block a user