Polishing contribution

Closes gh-31778
This commit is contained in:
rstoyanchev 2023-12-12 16:00:50 +00:00
parent 4d838c1092
commit 125e2902be
2 changed files with 34 additions and 32 deletions

View File

@ -20,11 +20,10 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import org.springframework.core.MethodParameter;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.MethodParameter;
import org.springframework.http.codec.multipart.FormFieldPart; import org.springframework.http.codec.multipart.FormFieldPart;
import org.springframework.http.codec.multipart.Part; import org.springframework.http.codec.multipart.Part;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -92,8 +91,7 @@ public class WebExchangeDataBinder extends WebDataBinder {
@Override @Override
protected boolean shouldConstructArgument(MethodParameter param) { protected boolean shouldConstructArgument(MethodParameter param) {
Class<?> type = param.nestedIfOptional().getNestedParameterType(); Class<?> type = param.nestedIfOptional().getNestedParameterType();
return (super.shouldConstructArgument(param) && return (super.shouldConstructArgument(param) && !Part.class.isAssignableFrom(type));
!MultipartFile.class.isAssignableFrom(type) && !Part.class.isAssignableFrom(type));
} }
/** /**

View File

@ -35,6 +35,7 @@ import org.springframework.http.MediaType;
import org.springframework.http.codec.FormHttpMessageWriter; import org.springframework.http.codec.FormHttpMessageWriter;
import org.springframework.http.codec.multipart.FilePart; import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.MultipartHttpMessageWriter; import org.springframework.http.codec.multipart.MultipartHttpMessageWriter;
import org.springframework.lang.Nullable;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
@ -59,7 +60,7 @@ public class WebExchangeDataBinderTests {
@BeforeEach @BeforeEach
public void setup() throws Exception { public void setup() {
this.testBean = new TestBean(); this.testBean = new TestBean();
this.binder = new WebExchangeDataBinder(this.testBean, "person"); this.binder = new WebExchangeDataBinder(this.testBean, "person");
this.binder.registerCustomEditor(ITestBean.class, new TestBeanPropertyEditor()); this.binder.registerCustomEditor(ITestBean.class, new TestBeanPropertyEditor());
@ -67,7 +68,7 @@ public class WebExchangeDataBinderTests {
@Test @Test
public void testBindingWithNestedObjectCreation() throws Exception { public void testBindingWithNestedObjectCreation() {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("spouse", "someValue"); formData.add("spouse", "someValue");
formData.add("spouse.name", "test"); formData.add("spouse.name", "test");
@ -78,7 +79,7 @@ public class WebExchangeDataBinderTests {
} }
@Test @Test
public void testFieldPrefixCausesFieldReset() throws Exception { public void testFieldPrefixCausesFieldReset() {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("_postProcessed", "visible"); formData.add("_postProcessed", "visible");
formData.add("postProcessed", "on"); formData.add("postProcessed", "on");
@ -91,7 +92,7 @@ public class WebExchangeDataBinderTests {
} }
@Test @Test
public void testFieldPrefixCausesFieldResetWithIgnoreUnknownFields() throws Exception { public void testFieldPrefixCausesFieldResetWithIgnoreUnknownFields() {
this.binder.setIgnoreUnknownFields(false); this.binder.setIgnoreUnknownFields(false);
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
@ -115,7 +116,7 @@ public class WebExchangeDataBinderTests {
} }
@Test @Test
public void testFieldDefault() throws Exception { public void testFieldDefault() {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("!postProcessed", "off"); formData.add("!postProcessed", "off");
formData.add("postProcessed", "on"); formData.add("postProcessed", "on");
@ -128,7 +129,7 @@ public class WebExchangeDataBinderTests {
} }
@Test @Test
public void testFieldDefaultPreemptsFieldMarker() throws Exception { public void testFieldDefaultPreemptsFieldMarker() {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("!postProcessed", "on"); formData.add("!postProcessed", "on");
formData.add("_postProcessed", "visible"); formData.add("_postProcessed", "visible");
@ -146,7 +147,7 @@ public class WebExchangeDataBinderTests {
} }
@Test @Test
public void testFieldDefaultNonBoolean() throws Exception { public void testFieldDefaultNonBoolean() {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("!name", "anonymous"); formData.add("!name", "anonymous");
formData.add("name", "Scott"); formData.add("name", "Scott");
@ -159,7 +160,7 @@ public class WebExchangeDataBinderTests {
} }
@Test @Test
public void testWithCommaSeparatedStringArray() throws Exception { public void testWithCommaSeparatedStringArray() {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("stringArray", "bar"); formData.add("stringArray", "bar");
formData.add("stringArray", "abc"); formData.add("stringArray", "abc");
@ -174,7 +175,7 @@ public class WebExchangeDataBinderTests {
} }
@Test @Test
public void testBindingWithNestedObjectCreationAndWrongOrder() throws Exception { public void testBindingWithNestedObjectCreationAndWrongOrder() {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("spouse.name", "test"); formData.add("spouse.name", "test");
formData.add("spouse", "someValue"); formData.add("spouse", "someValue");
@ -185,7 +186,7 @@ public class WebExchangeDataBinderTests {
} }
@Test @Test
public void testBindingWithQueryParams() throws Exception { public void testBindingWithQueryParams() {
String url = "/path?spouse=someValue&spouse.name=test"; String url = "/path?spouse=someValue&spouse.name=test";
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.post(url)); ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.post(url));
this.binder.bind(exchange).block(Duration.ofSeconds(5)); this.binder.bind(exchange).block(Duration.ofSeconds(5));
@ -195,7 +196,7 @@ public class WebExchangeDataBinderTests {
} }
@Test @Test
public void testMultipart() throws Exception { public void testMultipart() {
MultipartBean bean = new MultipartBean(); MultipartBean bean = new MultipartBean();
WebExchangeDataBinder binder = new WebExchangeDataBinder(bean); WebExchangeDataBinder binder = new WebExchangeDataBinder(bean);
@ -221,17 +222,17 @@ public class WebExchangeDataBinderTests {
} }
@Test @Test
public void testConstructorMultipart() throws Exception { public void testMultipartDataClass() {
WebExchangeDataBinder binder = new WebExchangeDataBinder(null); WebExchangeDataBinder binder = new WebExchangeDataBinder(null);
binder.setTargetType(ResolvableType.forClass(ConstructorMultipartBean.class)); binder.setTargetType(ResolvableType.forClass(MultipartDataClass.class));
MultiValueMap<String, Object> data = new LinkedMultiValueMap<>(); MultiValueMap<String, Object> data = new LinkedMultiValueMap<>();
data.add("part", new ClassPathResource("org/springframework/http/codec/multipart/foo.txt")); data.add("part", new ClassPathResource("org/springframework/http/codec/multipart/foo.txt"));
binder.construct(exchangeMultipart(data)).block(Duration.ofMillis(5000)); binder.construct(exchangeMultipart(data)).block(Duration.ofMillis(5000));
ConstructorMultipartBean bean = (ConstructorMultipartBean) binder.getTarget();
MultipartDataClass bean = (MultipartDataClass) binder.getTarget();
assertThat(bean.getPart().filename()).isEqualTo("foo.txt"); assertThat(bean.getPart().filename()).isEqualTo("foo.txt");
assertThat(bean.getNullableFilePart()).isNull(); assertThat(bean.getNullablePart()).isNull(); // gh-31778
} }
@ -257,10 +258,11 @@ public class WebExchangeDataBinderTests {
new MultipartHttpMessageWriter().write(Mono.just(multipartData), forClass(MultiValueMap.class), new MultipartHttpMessageWriter().write(Mono.just(multipartData), forClass(MultiValueMap.class),
MediaType.MULTIPART_FORM_DATA, request, Collections.emptyMap()).block(); MediaType.MULTIPART_FORM_DATA, request, Collections.emptyMap()).block();
return MockServerWebExchange.from(MockServerHttpRequest MockServerHttpRequest serverRequest = MockServerHttpRequest.post("/")
.post("/")
.contentType(request.getHeaders().getContentType()) .contentType(request.getHeaders().getContentType())
.body(request.getBody())); .body(request.getBody());
return MockServerWebExchange.from(serverRequest);
} }
@ -327,24 +329,26 @@ public class WebExchangeDataBinderTests {
} }
} }
private static class ConstructorMultipartBean {
private final FilePart part;
private final FilePart nullableFilePart;
public ConstructorMultipartBean( private static class MultipartDataClass {
FilePart part,
FilePart nullableFilePart private final FilePart part;
) {
@Nullable
private final FilePart nullablePart;
MultipartDataClass(FilePart part, @Nullable FilePart nullablePart) {
this.part = part; this.part = part;
this.nullableFilePart = nullableFilePart; this.nullablePart = nullablePart;
} }
public FilePart getPart() { public FilePart getPart() {
return part; return part;
} }
public FilePart getNullableFilePart() { @Nullable
return nullableFilePart; public FilePart getNullablePart() {
return nullablePart;
} }
} }
} }