Prior to this commit, gh-36255 introduced the new
`MultipartHttpMessageConverter`, focusing on multipart message
conversion in a separate converter. The `FormHttpMessageConverter` did
conflate URL encoded forms and multipart messages in the same converter.
With the introduction of the new converter and related types in the same
package (with `Part`, `FormFieldPart` and `FilePart`), we can now
revisit this arrangement.
This commit restricts the `FormHttpMessageConverter` to URL encoded
forms only and as a result, changes its implementation to only consider
`MultiValueMap<String, String>` types for reading and writing HTTP
messages. Because type erasure, this converter is now a
`SmartHttpMessageConverter` to get better type information with
`ResolvableType`.
As a result, the `AllEncompassingFormHttpMessageConverter` is formally
deprecated and replaced by the `MultipartHttpMessageConverter`, by
setting part converters explicitly in its constructor.
Closes gh-36256
@ -402,6 +402,27 @@ To serialize only a subset of the object properties, you can specify a {baeldung
@@ -402,6 +402,27 @@ To serialize only a subset of the object properties, you can specify a {baeldung
.toBodilessEntity();
----
==== URL encoded Forms
URL encoded forms, using the `"application/x-www-form-urlencoded"` media type, are useful for sending String key/values over the wire.
This is supported by the `FormHttpMessageConverter`, if the application uses a `MultiValueMap<String, String>` as source instance
or a target type.
For example:
[source,java,indent=0,subs="verbatim"]
----
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
To send multipart data, you need to provide a `MultiValueMap<String, Object>` whose values may be an `Object` for part content, a `Resource` for a file part, or an `HttpEntity` for part content with headers.
@ -419,18 +440,22 @@ For example:
@@ -419,18 +440,22 @@ For example:
In most cases, you do not have to specify the `Content-Type` for each part.
The content type is determined automatically based on the `HttpMessageConverter` chosen to serialize it or, in the case of a `Resource`, based on the file extension.
If necessary, you can explicitly provide the `MediaType` with an `HttpEntity` wrapper.
Once the `MultiValueMap` is ready, you can use it as the body of a `POST` request, using `RestClient.post().body(parts)` (or `RestTemplate.postForObject`).
The `Content-Type` is set to `multipart/form-data` by the `MultiPartHttpMessageConverter`.
As seen in the previous section, `MultiValueMap` types can also be used for URL encoded forms.
It is preferable to explicitly set the media type in the `Content-Type` or `Accept` HTTP request headers to ensure that the expected
message converter is used.
If the `MultiValueMap` contains at least one non-`String` value, the `Content-Type` is set to `multipart/form-data` by the `FormHttpMessageConverter`.
If the `MultiValueMap` has `String` values, the `Content-Type` defaults to `application/x-www-form-urlencoded`.
If necessary the `Content-Type` may also be set explicitly.
@ -23,13 +23,16 @@ For all converters, a default media type is used, but you can override it by set
@@ -23,13 +23,16 @@ For all converters, a default media type is used, but you can override it by set
By default, this converter supports all text media types(`text/{asterisk}`) and writes with a `Content-Type` of `text/plain`.
| `FormHttpMessageConverter`
| An `HttpMessageConverter` implementation that can read and write form data from the HTTP request and response.
| An `HttpMessageConverter` implementation that can read and write URL encoded forms.
By default, this converter reads and writes the `application/x-www-form-urlencoded` media type.
Form data is read from and written into a `MultiValueMap<String, String>`.
The converter can also write (but not read) multipart data read from a `MultiValueMap<String, Object>`.
By default, `multipart/form-data` is supported.
Additional multipart subtypes can be supported for writing form data.
Consult the javadoc for `FormHttpMessageConverter` for further details.
| `MultipartHttpMessageConverter`
| An `HttpMessageConverter` implementation that can read and write multipart messages.
`MultiValueMap<String, Object>` can be written to multipart messages, converting each part independently using
the configured message converters. Multipart messages can be read into `MultiValueMap<String, Part>`, each value
being a `Part` or one of its subtypes (`FormFieldPart` and `FilePart`).
By default, `multipart/form-data` is supported. Additional multipart subtypes can be supported for writing form data.
| `ByteArrayHttpMessageConverter`
| An `HttpMessageConverter` implementation that can read and write byte arrays from the HTTP request and response.
@ -1021,7 +1022,6 @@ public abstract class AbstractMockHttpServletRequestBuilder<B extends AbstractMo
@@ -1021,7 +1022,6 @@ public abstract class AbstractMockHttpServletRequestBuilder<B extends AbstractMo
@ -1038,7 +1038,8 @@ public abstract class AbstractMockHttpServletRequestBuilder<B extends AbstractMo
@@ -1038,7 +1038,8 @@ public abstract class AbstractMockHttpServletRequestBuilder<B extends AbstractMo
// We can't read multipart, so skip this supported media type.
continue;
}
if(supportedMediaType.includes(mediaType)){
returntrue;
}
@ -325,13 +120,12 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@@ -325,13 +120,12 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@ -341,8 +135,8 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@@ -341,8 +135,8 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@ -372,39 +166,13 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@@ -372,39 +166,13 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@ -436,7 +204,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@@ -436,7 +204,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@ -450,7 +218,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@@ -450,7 +218,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@ -458,265 +226,4 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@@ -458,265 +226,4 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
@ -170,6 +170,7 @@ public class MultipartHttpMessageConverter implements SmartHttpMessageConverter<
@@ -170,6 +170,7 @@ public class MultipartHttpMessageConverter implements SmartHttpMessageConverter<
@ -49,7 +50,7 @@ public class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConv
@@ -49,7 +50,7 @@ public class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConv
@ -58,12 +58,12 @@ public class FormContentFilter extends OncePerRequestFilter {
@@ -58,12 +58,12 @@ public class FormContentFilter extends OncePerRequestFilter {
Assert.notNull(converter,"FormHttpMessageConverter is required");
@ -105,7 +105,7 @@ public class FormContentFilter extends OncePerRequestFilter {
@@ -105,7 +105,7 @@ public class FormContentFilter extends OncePerRequestFilter {
@ -293,7 +295,9 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
@@ -293,7 +295,9 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
@ -579,7 +581,9 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
@@ -579,7 +581,9 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter