Skip to content

Commit 5861e96

Browse files
committed
Always specify charset for form data requests
Issue: SPR-16613
1 parent e00384a commit 5861e96

File tree

5 files changed

+33
-23
lines changed

5 files changed

+33
-23
lines changed

spring-web/src/main/java/org/springframework/http/codec/FormHttpMessageWriter.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -61,12 +61,15 @@ public class FormHttpMessageWriter implements HttpMessageWriter<MultiValueMap<St
6161

6262
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
6363

64-
private static final ResolvableType MULTIVALUE_TYPE =
65-
ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class);
64+
private static final MediaType DEFAULT_FORM_DATA_MEDIA_TYPE =
65+
new MediaType(MediaType.APPLICATION_FORM_URLENCODED, DEFAULT_CHARSET);
6666

6767
private static final List<MediaType> MEDIA_TYPES =
6868
Collections.singletonList(MediaType.APPLICATION_FORM_URLENCODED);
6969

70+
private static final ResolvableType MULTIVALUE_TYPE =
71+
ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class);
72+
7073

7174
private Charset defaultCharset = DEFAULT_CHARSET;
7275

@@ -117,13 +120,16 @@ public Mono<Void> write(Publisher<? extends MultiValueMap<String, String>> input
117120
ResolvableType elementType, @Nullable MediaType mediaType, ReactiveHttpOutputMessage message,
118121
Map<String, Object> hints) {
119122

120-
MediaType contentType = message.getHeaders().getContentType();
121-
if (contentType == null) {
122-
contentType = MediaType.APPLICATION_FORM_URLENCODED;
123-
message.getHeaders().setContentType(contentType);
123+
mediaType = (mediaType != null ? mediaType : DEFAULT_FORM_DATA_MEDIA_TYPE);
124+
Charset charset;
125+
if (mediaType.getCharset() == null) {
126+
charset = getDefaultCharset();
127+
mediaType = new MediaType(mediaType, charset);
124128
}
125-
126-
Charset charset = getMediaTypeCharset(contentType);
129+
else {
130+
charset = mediaType.getCharset();
131+
}
132+
message.getHeaders().setContentType(mediaType);
127133

128134
return Mono.from(inputStream).flatMap(form -> {
129135
String value = serializeForm(form, charset);

spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
9696

9797
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
9898

99+
private static final MediaType DEFAULT_FORM_DATA_MEDIA_TYPE =
100+
new MediaType(MediaType.APPLICATION_FORM_URLENCODED, DEFAULT_CHARSET);
101+
99102

100103
private List<MediaType> supportedMediaTypes = new ArrayList<>();
101104

@@ -290,15 +293,14 @@ private boolean isMultipart(MultiValueMap<String, ?> map, @Nullable MediaType co
290293
private void writeForm(MultiValueMap<String, String> form, @Nullable MediaType contentType,
291294
HttpOutputMessage outputMessage) throws IOException {
292295

293-
Charset charset;
294-
if (contentType != null) {
295-
outputMessage.getHeaders().setContentType(contentType);
296-
charset = (contentType.getCharset() != null ? contentType.getCharset() : this.charset);
297-
}
298-
else {
299-
outputMessage.getHeaders().setContentType(MediaType.APPLICATION_FORM_URLENCODED);
296+
contentType = (contentType != null ? contentType : DEFAULT_FORM_DATA_MEDIA_TYPE);
297+
Charset charset = contentType.getCharset();
298+
if (charset == null) {
300299
charset = this.charset;
300+
contentType = new MediaType(contentType, charset);
301301
}
302+
outputMessage.getHeaders().setContentType(contentType);
303+
302304
StringBuilder builder = new StringBuilder();
303305
for (Iterator<String> nameIterator = form.keySet().iterator(); nameIterator.hasNext();) {
304306
String name = nameIterator.next();

spring-web/src/test/java/org/springframework/http/codec/FormHttpMessageWriterTests.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222
import reactor.core.publisher.Mono;
2323

2424
import org.springframework.core.ResolvableType;
25+
import org.springframework.http.HttpHeaders;
2526
import org.springframework.http.MediaType;
2627
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
2728
import org.springframework.util.LinkedMultiValueMap;
@@ -79,8 +80,9 @@ public void writeForm() {
7980

8081
String responseBody = response.getBodyAsString().block();
8182
assertEquals("name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3", responseBody);
82-
assertEquals(MediaType.APPLICATION_FORM_URLENCODED, response.getHeaders().getContentType());
83-
assertEquals(responseBody.getBytes().length, response.getHeaders().getContentLength());
83+
HttpHeaders headers = response.getHeaders();
84+
assertEquals("application/x-www-form-urlencoded;charset=UTF-8", headers.getContentType().toString());
85+
assertEquals(responseBody.getBytes().length, headers.getContentLength());
8486
}
8587

8688
}

spring-web/src/test/java/org/springframework/http/converter/FormHttpMessageConverterTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -112,8 +112,8 @@ public void writeForm() throws IOException {
112112

113113
assertEquals("Invalid result", "name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3",
114114
outputMessage.getBodyAsString(StandardCharsets.UTF_8));
115-
assertEquals("Invalid content-type", new MediaType("application", "x-www-form-urlencoded"),
116-
outputMessage.getHeaders().getContentType());
115+
assertEquals("Invalid content-type", "application/x-www-form-urlencoded;charset=UTF-8",
116+
outputMessage.getHeaders().getContentType().toString());
117117
assertEquals("Invalid content-length", outputMessage.getBodyAsBytes().length,
118118
outputMessage.getHeaders().getContentLength());
119119
}

spring-web/src/test/java/org/springframework/web/client/AbstractMockWebServerTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private void assertFilePart(Buffer buffer, String disposition, String boundary,
165165
}
166166

167167
private MockResponse formRequest(RecordedRequest request) {
168-
assertEquals("application/x-www-form-urlencoded", request.getHeader("Content-Type"));
168+
assertEquals("application/x-www-form-urlencoded;charset=UTF-8", request.getHeader("Content-Type"));
169169
String body = request.getBody().readUtf8();
170170
assertThat(body, Matchers.containsString("name+1=value+1"));
171171
assertThat(body, Matchers.containsString("name+2=value+2%2B1"));

0 commit comments

Comments
 (0)