Write form data without charset parameter
This commit updates the content-type for form data to not include the charset, unless it is different from the default charset. Some servers don't handle charset parameter and the spec is unclear. See gh-31781
This commit is contained in:
committed by
Stéphane Nicoll
parent
08998376cc
commit
b8715811f8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,14 +60,9 @@ import org.springframework.util.MultiValueMap;
|
||||
public class FormHttpMessageWriter extends LoggingCodecSupport
|
||||
implements HttpMessageWriter<MultiValueMap<String, String>> {
|
||||
|
||||
/**
|
||||
* The default charset used by the writer.
|
||||
*/
|
||||
/** The default charset used by the writer. */
|
||||
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
|
||||
|
||||
private static final MediaType DEFAULT_FORM_DATA_MEDIA_TYPE =
|
||||
new MediaType(MediaType.APPLICATION_FORM_URLENCODED, DEFAULT_CHARSET);
|
||||
|
||||
private static final List<MediaType> MEDIA_TYPES =
|
||||
Collections.singletonList(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
|
||||
@@ -126,7 +121,7 @@ public class FormHttpMessageWriter extends LoggingCodecSupport
|
||||
mediaType = getMediaType(mediaType);
|
||||
message.getHeaders().setContentType(mediaType);
|
||||
|
||||
Charset charset = mediaType.getCharset() != null ? mediaType.getCharset() : getDefaultCharset();
|
||||
Charset charset = (mediaType.getCharset() != null ? mediaType.getCharset() : getDefaultCharset());
|
||||
|
||||
return Mono.from(inputStream).flatMap(form -> {
|
||||
logFormData(form, hints);
|
||||
@@ -138,16 +133,22 @@ public class FormHttpMessageWriter extends LoggingCodecSupport
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content type used to write forms, either the given media type
|
||||
* or otherwise {@code application/x-www-form-urlencoded}.
|
||||
* @param mediaType the media type passed to {@link #write}, or {@code null}
|
||||
* @return the content type to use
|
||||
*/
|
||||
protected MediaType getMediaType(@Nullable MediaType mediaType) {
|
||||
if (mediaType == null) {
|
||||
return DEFAULT_FORM_DATA_MEDIA_TYPE;
|
||||
return MediaType.APPLICATION_FORM_URLENCODED;
|
||||
}
|
||||
else if (mediaType.getCharset() == null) {
|
||||
return new MediaType(mediaType, getDefaultCharset());
|
||||
}
|
||||
else {
|
||||
return mediaType;
|
||||
// Some servers don't handle charset parameter and spec is unclear,
|
||||
// Add it only if it is not DEFAULT_CHARSET.
|
||||
if (mediaType.getCharset() == null && this.defaultCharset != DEFAULT_CHARSET) {
|
||||
return new MediaType(mediaType, this.defaultCharset);
|
||||
}
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
private void logFormData(MultiValueMap<String, String> form, Map<String, Object> hints) {
|
||||
|
||||
@@ -154,14 +154,9 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class FormHttpMessageConverter implements HttpMessageConverter<MultiValueMap<String, ?>> {
|
||||
|
||||
/**
|
||||
* The default charset used by the converter.
|
||||
*/
|
||||
/** The default charset used by the converter. */
|
||||
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
|
||||
|
||||
private static final MediaType DEFAULT_FORM_DATA_MEDIA_TYPE =
|
||||
new MediaType(MediaType.APPLICATION_FORM_URLENCODED, DEFAULT_CHARSET);
|
||||
|
||||
|
||||
private List<MediaType> supportedMediaTypes = new ArrayList<>();
|
||||
|
||||
@@ -387,14 +382,13 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||
return false;
|
||||
}
|
||||
|
||||
private void writeForm(MultiValueMap<String, Object> formData, @Nullable MediaType contentType,
|
||||
private void writeForm(MultiValueMap<String, Object> formData, @Nullable MediaType mediaType,
|
||||
HttpOutputMessage outputMessage) throws IOException {
|
||||
|
||||
contentType = getFormContentType(contentType);
|
||||
outputMessage.getHeaders().setContentType(contentType);
|
||||
mediaType = getFormContentType(mediaType);
|
||||
outputMessage.getHeaders().setContentType(mediaType);
|
||||
|
||||
Charset charset = contentType.getCharset();
|
||||
Assert.notNull(charset, "No charset"); // should never occur
|
||||
Charset charset = (mediaType.getCharset() != null ? mediaType.getCharset() : this.charset);
|
||||
|
||||
byte[] bytes = serializeForm(formData, charset).getBytes(charset);
|
||||
outputMessage.getHeaders().setContentLength(bytes.length);
|
||||
@@ -418,26 +412,22 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content type used to write forms, given the preferred content type.
|
||||
* By default, this method returns the given content type, but adds the
|
||||
* {@linkplain #setCharset(Charset) charset} if it does not have one.
|
||||
* If {@code contentType} is {@code null},
|
||||
* {@code application/x-www-form-urlencoded; charset=UTF-8} is returned.
|
||||
* <p>Subclasses can override this method to change this behavior.
|
||||
* @param contentType the preferred content type (can be {@code null})
|
||||
* @return the content type to be used
|
||||
* Return the content type used to write forms, either the given content type
|
||||
* or otherwise {@code application/x-www-form-urlencoded}.
|
||||
* @param contentType the content type passed to {@link #write}, or {@code null}
|
||||
* @return the content type to use
|
||||
* @since 5.2.2
|
||||
*/
|
||||
protected MediaType getFormContentType(@Nullable MediaType contentType) {
|
||||
if (contentType == null) {
|
||||
return DEFAULT_FORM_DATA_MEDIA_TYPE;
|
||||
return MediaType.APPLICATION_FORM_URLENCODED;
|
||||
}
|
||||
else if (contentType.getCharset() == null) {
|
||||
// Some servers don't handle charset parameter and spec is unclear,
|
||||
// Add it only if it is not DEFAULT_CHARSET.
|
||||
if (contentType.getCharset() == null && this.charset != DEFAULT_CHARSET) {
|
||||
return new MediaType(contentType, this.charset);
|
||||
}
|
||||
else {
|
||||
return contentType;
|
||||
}
|
||||
return contentType;
|
||||
}
|
||||
|
||||
protected String serializeForm(MultiValueMap<String, Object> formData, Charset charset) {
|
||||
|
||||
Reference in New Issue
Block a user