HTTPCLIENT-2325 Avoid adding "; charset=" for multipart/form-data requests

Previusly, "charset" parameter was added to the Content-Type header, however adding "charset=..."
is not specified in RFC 7578, and it causes issues with (flawed?) HTTP servers.

The change does not modify ContentType.MULTIPART_FORM_DATA, and it might have backward compatibility
side-effects.

See
* https://github.com/apache/jmeter/issues/6250
* 6e56950cdf
* https://bz.apache.org/bugzilla/show_bug.cgi?id=61384
* https://github.com/akka/akka-http/issues/338
This commit is contained in:
Vladimir Sitnikov 2024-03-18 13:43:46 +03:00 committed by Oleg Kalnichevski
parent ccff40612c
commit 3b9bc89c26
3 changed files with 33 additions and 12 deletions

View File

@ -253,12 +253,7 @@ import org.apache.hc.core5.util.Args;
if (charsetCopy == null && contentType != null) {
charsetCopy = contentType.getCharset();
}
final List<NameValuePair> paramsList = new ArrayList<>(2);
paramsList.add(new BasicNameValuePair("boundary", boundaryCopy));
if (charsetCopy != null) {
paramsList.add(new BasicNameValuePair("charset", charsetCopy.name()));
}
final NameValuePair[] params = paramsList.toArray(EMPTY_NAME_VALUE_ARRAY);
final NameValuePair[] params = new NameValuePair[]{new BasicNameValuePair("boundary", boundaryCopy)};
final ContentType contentTypeCopy;
if (contentType != null) {

View File

@ -88,7 +88,7 @@ public class TestMultipartEntityBuilder {
.setLaxMode()
.buildEntity();
Assertions.assertNotNull(entity);
Assertions.assertEquals("application/xml; boundary=blah-blah; charset=UTF-8", entity.getContentType());
Assertions.assertEquals("application/xml; charset=UTF-8; boundary=blah-blah", entity.getContentType());
}
@Test
@ -99,11 +99,36 @@ public class TestMultipartEntityBuilder {
new BasicNameValuePair("charset", "ascii")))
.buildEntity();
Assertions.assertNotNull(entity);
Assertions.assertEquals("multipart/form-data; boundary=yada-yada; charset=US-ASCII", entity.getContentType());
Assertions.assertEquals("multipart/form-data; boundary=yada-yada; charset=ascii", entity.getContentType());
Assertions.assertEquals("yada-yada", entity.getMultipart().boundary);
Assertions.assertEquals(StandardCharsets.US_ASCII, entity.getMultipart().charset);
}
@Test
public void testMultipartDefaultContentTypeOmitsCharset() throws Exception {
final MultipartFormEntity entity = MultipartEntityBuilder.create()
.setCharset(StandardCharsets.UTF_8)
.setBoundary("yada-yada")
.buildEntity();
Assertions.assertNotNull(entity);
Assertions.assertEquals("multipart/mixed; boundary=yada-yada", entity.getContentType());
Assertions.assertEquals("yada-yada", entity.getMultipart().boundary);
}
@Test
public void testMultipartFormDataContentTypeOmitsCharset() throws Exception {
// Note: org.apache.hc.core5.http.ContentType.MULTIPART_FORM_DATA uses StandardCharsets.ISO_8859_1,
// so we create a custom ContentType here
final MultipartFormEntity entity = MultipartEntityBuilder.create()
.setContentType(ContentType.create("multipart/form-data"))
.setCharset(StandardCharsets.UTF_8)
.setBoundary("yada-yada")
.buildEntity();
Assertions.assertNotNull(entity);
Assertions.assertEquals("multipart/form-data; boundary=yada-yada", entity.getContentType());
Assertions.assertEquals("yada-yada", entity.getMultipart().boundary);
}
@Test
public void testMultipartCustomContentTypeParameterOverrides() throws Exception {
final MultipartFormEntity entity = MultipartEntityBuilder.create()
@ -116,7 +141,7 @@ public class TestMultipartEntityBuilder {
.setLaxMode()
.buildEntity();
Assertions.assertNotNull(entity);
Assertions.assertEquals("multipart/form-data; boundary=blah-blah; charset=UTF-8; my=stuff",
Assertions.assertEquals("multipart/form-data; boundary=blah-blah; charset=ascii; my=stuff",
entity.getContentType());
}
@ -130,7 +155,7 @@ public class TestMultipartEntityBuilder {
eb.buildEntity();
final MultipartFormEntity entity = eb.buildEntity();
Assertions.assertNotNull(entity);
Assertions.assertEquals("multipart/related; boundary=yada-yada; charset=US-ASCII; my=stuff",
Assertions.assertEquals("multipart/related; boundary=yada-yada; charset=ascii; my=stuff",
entity.getContentType());
}

View File

@ -59,8 +59,9 @@ public class TestMultipartFormHttpEntity {
Assertions.assertNotNull(p1);
Assertions.assertEquals("whatever", p1.getValue());
final NameValuePair p2 = elem.getParameterByName("charset");
Assertions.assertNotNull(p2);
Assertions.assertEquals("UTF-8", p2.getValue());
Assertions.assertNull(p2,
"RFC7578 does not mention charset parameter for Content-Type, " +
"so no charset should be present for MultipartEntity.getContentType()");
}
@Test