Exclude Part from nested constructor binding in WebFlux

See gh-31778
This commit is contained in:
HeartPattern 2023-12-07 15:59:25 +09:00 committed by rstoyanchev
parent c75c0ae2d5
commit 4d838c1092
2 changed files with 43 additions and 0 deletions

View File

@ -20,6 +20,8 @@ import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.springframework.core.MethodParameter;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Mono;
import org.springframework.beans.MutablePropertyValues;
@ -87,6 +89,13 @@ public class WebExchangeDataBinder extends WebDataBinder {
.then();
}
@Override
protected boolean shouldConstructArgument(MethodParameter param) {
Class<?> type = param.nestedIfOptional().getNestedParameterType();
return (super.shouldConstructArgument(param) &&
!MultipartFile.class.isAssignableFrom(type) && !Part.class.isAssignableFrom(type));
}
/**
* Bind query parameters, form data, or multipart form data to the binder target.
* @param exchange the current exchange

View File

@ -28,6 +28,7 @@ import reactor.core.publisher.Mono;
import org.springframework.beans.testfixture.beans.ITestBean;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
@ -219,6 +220,19 @@ public class WebExchangeDataBinderTests {
assertThat(bean.getSomePartList().get(1).filename()).isEqualTo("spring.png");
}
@Test
public void testConstructorMultipart() throws Exception {
WebExchangeDataBinder binder = new WebExchangeDataBinder(null);
binder.setTargetType(ResolvableType.forClass(ConstructorMultipartBean.class));
MultiValueMap<String, Object> data = new LinkedMultiValueMap<>();
data.add("part", new ClassPathResource("org/springframework/http/codec/multipart/foo.txt"));
binder.construct(exchangeMultipart(data)).block(Duration.ofMillis(5000));
ConstructorMultipartBean bean = (ConstructorMultipartBean) binder.getTarget();
assertThat(bean.getPart().filename()).isEqualTo("foo.txt");
assertThat(bean.getNullableFilePart()).isNull();
}
private ServerWebExchange exchange(MultiValueMap<String, String> formData) {
@ -313,4 +327,24 @@ public class WebExchangeDataBinderTests {
}
}
private static class ConstructorMultipartBean {
private final FilePart part;
private final FilePart nullableFilePart;
public ConstructorMultipartBean(
FilePart part,
FilePart nullableFilePart
) {
this.part = part;
this.nullableFilePart = nullableFilePart;
}
public FilePart getPart() {
return part;
}
public FilePart getNullableFilePart() {
return nullableFilePart;
}
}
}