Affects: 6.0.5 (perhaps down to 5.0, the since value on BodyInserters)
Currently in BodyInserters, FormInserter only supports a blocking supply of values, and MultipartInserter extends that interface with support for values from a Publisher. Each interface's Default[...] implementation then provides the relevant MediaType when inserting the content. The async support is therefore coupled with using MediaType.MULTIPART_FORM_DATA.
It would be nice if the async support were available in FormInserter/DefaultFormInserter, such that a client could provide the form values reactively while still using MediaType.APPLICATION_FORM_URLENCODED / FORM_DATA_TYPE.
Comment From: poutsma
As it turns out, you can use the FormPartEvent API to accomplish what you want, and then use the resulting Flux<FormPartEvent> as body. I have added a tests that shows how to do this here: https://github.com/spring-projects/spring-framework/blob/faaf3a61f2944d80b8919c8900325db097944f24/spring-web/src/test/java/org/springframework/http/codec/multipart/PartEventHttpMessageWriterTests.java#L99
Comment From: nmck257
Thanks for that.
I wasn't actually able to accomplish my goal with FluxFormPartEvent. This sample:
WebClient.create().post().uri("http://localhost:%s".formatted(mockWebServer.getPort()))
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(Flux.concat(Mono.just(FormPartEvent.create("key", "value"))), PartEvent.class)
.retrieve()
.toBodilessEntity()
.block();
...yields an exception like this:
org.springframework.web.reactive.function.client.WebClientRequestException: Content type 'application/x-www-form-urlencoded' not supported for bodyType=org.springframework.http.codec.multipart.PartEvent
Looks like the default PartEventHttpMessageWriter is only configured for MediaType.MULTIPART_FORM_DATA.
But after trying that, I did have success with something more like:
WebClient.create().post().uri("http://localhost:%s".formatted(mockWebServer.getPort()))
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(Mono.just(new LinkedMultiValueMap()), MultiValueMap.class)
.retrieve()
.toBodilessEntity()
.block();
...reliant on MultipartHttpMessageWriter. Maybe there's value in updating the javadocs for BodyInserters::fromFormData to call out alternatives like this?
(tested using spring-framework 6.0.12)