diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java index d8e72697b5..b014d67343 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java @@ -615,6 +615,17 @@ public interface WebTestClient { /** * Set the body of the request to the given synchronous {@code Object} and * perform the request. + *
This method is a convenient shortcut for: + *
+ * .body(BodyInserters.fromObject(object)) + *+ *
The body can be a + * {@link org.springframework.util.MultiValueMap MultiValueMap} to create + * a multipart request. The values in the {@code MultiValueMap} can be + * any Object representing the body of the part, or an + * {@link org.springframework.http.HttpEntity HttpEntity} representing a + * part with body and headers. The {@code MultiValueMap} can be built + * conveniently using * @param body the {@code Object} to write to the request * @return a {@code Mono} with the response */ diff --git a/spring-web/src/main/java/org/springframework/web/client/RestOperations.java b/spring-web/src/main/java/org/springframework/web/client/RestOperations.java index 2a0ad67241..69da49ba5e 100644 --- a/spring-web/src/main/java/org/springframework/web/client/RestOperations.java +++ b/spring-web/src/main/java/org/springframework/web/client/RestOperations.java @@ -149,9 +149,13 @@ public interface RestOperations { * the {@code Location} header. This header typically indicates where the new resource is stored. *
URI Template variables are expanded using the given URI variables, if any. *
The {@code request} parameter can be a {@link HttpEntity} in order to - * add additional HTTP headers to the request. The body of the entity, or {@code request} itself, - * can be a {@link org.springframework.http.client.MultipartBodyBuilder MultiValueMap} to - * simulate a multipart from submission. + * add additional HTTP headers to the request. + *
The body of the entity, or {@code request} itself, can be a + * {@link org.springframework.util.MultiValueMap MultiValueMap} to create a multipart request. + * The values in the {@code MultiValueMap} can be any Object representing the body of the part, + * or an {@link org.springframework.http.HttpEntity HttpEntity} representing a part with body + * and headers. The {@code MultiValueMap} can be built conveniently using + * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. * @param url the URL * @param request the Object to be POSTed (may be {@code null}) * @param uriVariables the variables to expand the template @@ -166,9 +170,13 @@ public interface RestOperations { * the {@code Location} header. This header typically indicates where the new resource is stored. *
URI Template variables are expanded using the given map. *
The {@code request} parameter can be a {@link HttpEntity} in order to - * add additional HTTP headers to the request. The body of the entity, or {@code request} itself, - * can be a {@link org.springframework.http.client.MultipartBodyBuilder MultiValueMap} to - * simulate a multipart from submission. + * add additional HTTP headers to the request + *
The body of the entity, or {@code request} itself, can be a + * {@link org.springframework.util.MultiValueMap MultiValueMap} to create a multipart request. + * The values in the {@code MultiValueMap} can be any Object representing the body of the part, + * or an {@link org.springframework.http.HttpEntity HttpEntity} representing a part with body + * and headers. The {@code MultiValueMap} can be built conveniently using + * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. * @param url the URL * @param request the Object to be POSTed (may be {@code null}) * @param uriVariables the variables to expand the template @@ -183,9 +191,13 @@ public interface RestOperations { * Create a new resource by POSTing the given object to the URL, and returns the value of the * {@code Location} header. This header typically indicates where the new resource is stored. *
The {@code request} parameter can be a {@link HttpEntity} in order to - * add additional HTTP headers to the request. The body of the entity, or {@code request} itself, - * can be a {@link org.springframework.http.client.MultipartBodyBuilder MultiValueMap} to - * simulate a multipart from submission. + * add additional HTTP headers to the request. + *
The body of the entity, or {@code request} itself, can be a + * {@link org.springframework.util.MultiValueMap MultiValueMap} to create a multipart request. + * The values in the {@code MultiValueMap} can be any Object representing the body of the part, + * or an {@link org.springframework.http.HttpEntity HttpEntity} representing a part with body + * and headers. The {@code MultiValueMap} can be built conveniently using + * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. * @param url the URL * @param request the Object to be POSTed (may be {@code null}) * @return the value for the {@code Location} header @@ -199,9 +211,13 @@ public interface RestOperations { * and returns the representation found in the response. *
URI Template variables are expanded using the given URI variables, if any. *
The {@code request} parameter can be a {@link HttpEntity} in order to - * add additional HTTP headers to the request. The body of the entity, or {@code request} itself, - * can be a {@link org.springframework.http.client.MultipartBodyBuilder MultiValueMap} to - * simulate a multipart from submission. + * add additional HTTP headers to the request. + *
The body of the entity, or {@code request} itself, can be a + * {@link org.springframework.util.MultiValueMap MultiValueMap} to create a multipart request. + * The values in the {@code MultiValueMap} can be any Object representing the body of the part, + * or an {@link org.springframework.http.HttpEntity HttpEntity} representing a part with body + * and headers. The {@code MultiValueMap} can be built conveniently using + * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. * @param url the URL * @param request the Object to be POSTed (may be {@code null}) * @param responseType the type of the return value @@ -218,9 +234,13 @@ public interface RestOperations { * and returns the representation found in the response. *
URI Template variables are expanded using the given map. *
The {@code request} parameter can be a {@link HttpEntity} in order to - * add additional HTTP headers to the request. The body of the entity, or {@code request} itself, - * can be a {@link org.springframework.http.client.MultipartBodyBuilder MultiValueMap} to - * simulate a multipart from submission. + * add additional HTTP headers to the request. + *
The body of the entity, or {@code request} itself, can be a + * {@link org.springframework.util.MultiValueMap MultiValueMap} to create a multipart request. + * The values in the {@code MultiValueMap} can be any Object representing the body of the part, + * or an {@link org.springframework.http.HttpEntity HttpEntity} representing a part with body + * and headers. The {@code MultiValueMap} can be built conveniently using + * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. * @param url the URL * @param request the Object to be POSTed (may be {@code null}) * @param responseType the type of the return value @@ -236,9 +256,13 @@ public interface RestOperations { * Create a new resource by POSTing the given object to the URL, * and returns the representation found in the response. *
The {@code request} parameter can be a {@link HttpEntity} in order to - * add additional HTTP headers to the request. The body of the entity, or {@code request} itself, - * can be a {@link org.springframework.http.client.MultipartBodyBuilder MultiValueMap} to - * simulate a multipart from submission. + * add additional HTTP headers to the request. + *
The body of the entity, or {@code request} itself, can be a + * {@link org.springframework.util.MultiValueMap MultiValueMap} to create a multipart request. + * The values in the {@code MultiValueMap} can be any Object representing the body of the part, + * or an {@link org.springframework.http.HttpEntity HttpEntity} representing a part with body + * and headers. The {@code MultiValueMap} can be built conveniently using + * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. * @param url the URL * @param request the Object to be POSTed (may be {@code null}) * @param responseType the type of the return value @@ -253,9 +277,13 @@ public interface RestOperations { * and returns the response as {@link ResponseEntity}. *
URI Template variables are expanded using the given URI variables, if any. *
The {@code request} parameter can be a {@link HttpEntity} in order to - * add additional HTTP headers to the request. The body of the entity, or {@code request} itself, - * can be a {@link org.springframework.http.client.MultipartBodyBuilder MultiValueMap} to - * simulate a multipart from submission. + * add additional HTTP headers to the request. + *
The body of the entity, or {@code request} itself, can be a + * {@link org.springframework.util.MultiValueMap MultiValueMap} to create a multipart request. + * The values in the {@code MultiValueMap} can be any Object representing the body of the part, + * or an {@link org.springframework.http.HttpEntity HttpEntity} representing a part with body + * and headers. The {@code MultiValueMap} can be built conveniently using + * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. * @param url the URL * @param request the Object to be POSTed (may be {@code null}) * @param uriVariables the variables to expand the template @@ -271,9 +299,13 @@ public interface RestOperations { * and returns the response as {@link HttpEntity}. *
URI Template variables are expanded using the given map. *
The {@code request} parameter can be a {@link HttpEntity} in order to - * add additional HTTP headers to the request. The body of the entity, or {@code request} itself, - * can be a {@link org.springframework.http.client.MultipartBodyBuilder MultiValueMap} to - * simulate a multipart from submission. + * add additional HTTP headers to the request. + *
The body of the entity, or {@code request} itself, can be a + * {@link org.springframework.util.MultiValueMap MultiValueMap} to create a multipart request. + * The values in the {@code MultiValueMap} can be any Object representing the body of the part, + * or an {@link org.springframework.http.HttpEntity HttpEntity} representing a part with body + * and headers. The {@code MultiValueMap} can be built conveniently using + * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. * @param url the URL * @param request the Object to be POSTed (may be {@code null}) * @param uriVariables the variables to expand the template @@ -288,9 +320,13 @@ public interface RestOperations { * Create a new resource by POSTing the given object to the URL, * and returns the response as {@link ResponseEntity}. *
The {@code request} parameter can be a {@link HttpEntity} in order to - * add additional HTTP headers to the request. The body of the entity, or {@code request} itself, - * can be a {@link org.springframework.http.client.MultipartBodyBuilder MultiValueMap} to - * simulate a multipart from submission. + * add additional HTTP headers to the request. + *
The body of the entity, or {@code request} itself, can be a + * {@link org.springframework.util.MultiValueMap MultiValueMap} to create a multipart request. + * The values in the {@code MultiValueMap} can be any Object representing the body of the part, + * or an {@link org.springframework.http.HttpEntity HttpEntity} representing a part with body + * and headers. The {@code MultiValueMap} can be built conveniently using + * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. * @param url the URL * @param request the Object to be POSTed (may be {@code null}) * @return the converted object diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserters.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserters.java index 902319a9d6..fb0380ba06 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserters.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyInserters.java @@ -220,10 +220,13 @@ public abstract class BodyInserters { /** * Return a {@code FormInserter} that writes the given {@code MultiValueMap} - * as multipart data. The {@code multipartData} parameter can conveniently be built using the - * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. - * Note that the returned inserter allows for additional entries to be added - * via {@link FormInserter#with(String, Object)}. + * as multipart data. The values in the {@code MultiValueMap} can be any + * Object representing the body of the part, or an + * {@link org.springframework.http.HttpEntity HttpEntity} representing a part + * with body and headers. The {@code MultiValueMap} can be built conveniently + * using {@link org.springframework.http.client.MultipartBodyBuilder + * MultipartBodyBuilder}. Also the returned inserter allows for additional + * entries to be added via {@link FormInserter#with(String, Object)}. * *
Note: you can also use the {@code syncBody(Object)} * method in the request builders of both the {@code WebClient} and @@ -245,15 +248,13 @@ public abstract class BodyInserters { } /** - * Return a {@code FormInserter} that writes the key-value pair as multipart data. The - * {@code multipartData} parameter can conveniently be built using the - * {@link org.springframework.http.client.MultipartBodyBuilder MultipartBodyBuilder}. - * Note that the returned inserter allows for additional entries to be added - * via {@link FormInserter#with(String, Object)}. - * {@link FormInserter#with(String, Object)}. - * @param key the key to add to the form - * @param value the value to add to the form - * @return a {@code FormInserter} that writes multipart data + * A variant of {@link #fromMultipartData(MultiValueMap)} for adding + * parts as name-value pairs in-line vs building a {@code MultiValueMap} + * and passing it in. + * @param key the part name + * @param value the part value, an Object or {@code HttpEntity} + * @return a {@code FormInserter} that can writes the provided multipart + * data and also allows adding more parts */ // Note that the returned BodyInserter is parameterized to ClientHttpRequest, not // ReactiveHttpOutputMessage like other methods, since sending form data only typically happens diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java index 1d048db873..d697c4b3bc 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java @@ -544,9 +544,17 @@ public interface WebClient { /** * Set the body of the request to the given synchronous {@code Object}. - *
This method is a convenient shortcut for {@link #body(BodyInserter)} with a - * {@linkplain org.springframework.web.reactive.function.BodyInserters#fromObject - * Object body inserter}. + *
This method is a convenient shortcut for: + *
+ * .body(BodyInserters.fromObject(object)) + *+ *
The body can be a
+ * {@link org.springframework.util.MultiValueMap MultiValueMap} to create
+ * a multipart request. The values in the {@code MultiValueMap} can be
+ * any Object representing the body of the part, or an
+ * {@link org.springframework.http.HttpEntity HttpEntity} representing a
+ * part with body and headers. The {@code MultiValueMap} can be built
+ * conveniently using
* @param body the {@code Object} to write to the request
* @return this builder
*/
diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/MultipartIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/MultipartIntegrationTests.java
index 1ed3236276..2f183d7520 100644
--- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/MultipartIntegrationTests.java
+++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/MultipartIntegrationTests.java
@@ -23,10 +23,12 @@ import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
+import org.springframework.http.client.MultipartBodyBuilder;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.FormFieldPart;
import org.springframework.http.codec.multipart.Part;
@@ -75,16 +77,11 @@ public class MultipartIntegrationTests extends AbstractRouterFunctionIntegration
.verifyComplete();
}
- private MultiValueMap