Simplified MIME multipart generation modes (legacy, strict and extended)

This commit is contained in:
Oleg Kalnichevski 2019-12-20 10:40:54 +01:00
parent 56463de35d
commit 54a341ea92
6 changed files with 43 additions and 28 deletions

View File

@ -28,18 +28,35 @@
package org.apache.hc.client5.http.entity.mime;
/**
* MIME compliance mode.
*
* @since 4.0
*/
public enum HttpMultipartMode {
/** RFC 822, RFC 2045, RFC 2046 compliant */
/**
* Legacy compatibility mode.
* <p>
* In this mode only the most essential fields are generated
* such as Content-Type and Content-Disposition.
*/
LEGACY,
/**
* Strict MIME specification conformance.
* <p>
* Presently conforms to RFC 822, RFC 2045, RFC 2046.
*/
STRICT,
/** browser-compatible mode, i.e. only write Content-Disposition; use content charset */
BROWSER_COMPATIBLE,
/** RFC 6532 compliant */
RFC6532,
/** RFC 7578 compliant */
RFC7578
/**
* Extended MIME specification conformance.
* <p>
* In this mode header field values may contain international UTF-8 encoded
* characters.
* <p>
* Presently conforms to RFC 6532 and RFC 7578.
*/
EXTENDED,
}

View File

@ -38,11 +38,11 @@ import java.util.List;
*
* @since 4.3
*/
class HttpBrowserCompatibleMultipart extends AbstractMultipartFormat {
class LegacyMultipart extends AbstractMultipartFormat {
private final List<MultipartPart> parts;
public HttpBrowserCompatibleMultipart(
public LegacyMultipart(
final Charset charset,
final String boundary,
final List<MultipartPart> parts) {

View File

@ -56,9 +56,6 @@ public class MultipartEntityBuilder {
"-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
.toCharArray();
private final static String FORM_SUBTYPE = "form-data";
private final static String MIXED_SUBTYPE = "mixed";
private ContentType contentType;
private HttpMultipartMode mode = HttpMultipartMode.STRICT;
private String boundary = null;
@ -78,7 +75,7 @@ public class MultipartEntityBuilder {
}
public MultipartEntityBuilder setLaxMode() {
this.mode = HttpMultipartMode.BROWSER_COMPATIBLE;
this.mode = HttpMultipartMode.LEGACY;
return this;
}
@ -219,9 +216,9 @@ public class MultipartEntityBuilder {
}
if (formData) {
contentTypeCopy = ContentType.create("multipart/" + FORM_SUBTYPE, params);
contentTypeCopy = ContentType.MULTIPART_FORM_DATA.withParameters(params);
} else {
contentTypeCopy = ContentType.create("multipart/" + MIXED_SUBTYPE, params);
contentTypeCopy = ContentType.create("multipart/mixed", params);
}
}
final List<MultipartPart> multipartPartsCopy = multipartParts != null ? new ArrayList<>(multipartParts) :
@ -229,17 +226,18 @@ public class MultipartEntityBuilder {
final HttpMultipartMode modeCopy = mode != null ? mode : HttpMultipartMode.STRICT;
final AbstractMultipartFormat form;
switch (modeCopy) {
case BROWSER_COMPATIBLE:
form = new HttpBrowserCompatibleMultipart(charsetCopy, boundaryCopy, multipartPartsCopy);
case LEGACY:
form = new LegacyMultipart(charsetCopy, boundaryCopy, multipartPartsCopy);
break;
case RFC6532:
form = new HttpRFC6532Multipart(charsetCopy, boundaryCopy, multipartPartsCopy);
break;
case RFC7578:
if (charsetCopy == null) {
charsetCopy = StandardCharsets.UTF_8;
case EXTENDED:
if (ContentType.MULTIPART_FORM_DATA.isSameMimeType(ContentType.MULTIPART_FORM_DATA)) {
if (charsetCopy == null) {
charsetCopy = StandardCharsets.UTF_8;
}
form = new HttpRFC7578Multipart(charsetCopy, boundaryCopy, multipartPartsCopy);
} else {
form = new HttpRFC6532Multipart(charsetCopy, boundaryCopy, multipartPartsCopy);
}
form = new HttpRFC7578Multipart(charsetCopy, boundaryCopy, multipartPartsCopy);
break;
default:
form = new HttpStrictMultipart(StandardCharsets.US_ASCII, boundaryCopy, multipartPartsCopy);

View File

@ -58,7 +58,7 @@ public class TestMultipartEntityBuilder {
.setLaxMode()
.buildEntity();
Assert.assertNotNull(entity);
Assert.assertTrue(entity.getMultipart() instanceof HttpBrowserCompatibleMultipart);
Assert.assertTrue(entity.getMultipart() instanceof LegacyMultipart);
Assert.assertEquals("blah-blah", entity.getMultipart().boundary);
Assert.assertEquals(StandardCharsets.UTF_8, entity.getMultipart().charset);
}
@ -151,7 +151,7 @@ public class TestMultipartEntityBuilder {
parameters.add(new BasicNameValuePair(MimeConsts.FIELD_PARAM_FILENAME, "hello \u03BA\u03CC\u03C3\u03BC\u03B5!%"));
final MultipartFormEntity entity = MultipartEntityBuilder.create()
.setMode(HttpMultipartMode.RFC7578)
.setMode(HttpMultipartMode.EXTENDED)
.setBoundary("xxxxxxxxxxxxxxxxxxxxxxxx")
.addPart(new FormBodyPartBuilder()
.setName("test")

View File

@ -300,7 +300,7 @@ public class TestMultipartForm {
final FormBodyPart p2 = FormBodyPartBuilder.create(
"field2",
new InputStreamBody(new FileInputStream(tmpfile), s2 + ".tmp")).build();
final HttpBrowserCompatibleMultipart multipart = new HttpBrowserCompatibleMultipart(
final LegacyMultipart multipart = new LegacyMultipart(
StandardCharsets.UTF_8, "foo",
Arrays.<MultipartPart>asList(p1, p2));

View File

@ -264,7 +264,7 @@ public class TestMultipartMixed {
@SuppressWarnings("resource")
final MultipartPart p2 = MultipartPartBuilder.create(
new InputStreamBody(new FileInputStream(tmpfile), s2 + ".tmp")).build();
final HttpBrowserCompatibleMultipart multipart = new HttpBrowserCompatibleMultipart(
final LegacyMultipart multipart = new LegacyMultipart(
StandardCharsets.UTF_8, "foo",
Arrays.<MultipartPart>asList(p1, p2));