You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2017/09/30 21:24:18 UTC

[2/3] httpcomponents-client git commit: HTTPCLIENT-293 Refactored code in order to support multipart header field parameters in the data model and postpone the formatting and encoding of the parameters until the moment written into a stream, which is ess

HTTPCLIENT-293 Refactored code in order to support multipart header field parameters in the data model and postpone the formatting and encoding of the parameters until the moment written into a stream, which is essential in order to avoid multiple encodings of the same value.


Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/commit/582b2806
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/tree/582b2806
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/diff/582b2806

Branch: refs/heads/4.6.x
Commit: 582b28060335c443f971b7fe02bbfc9f3d44bf44
Parents: 258d753
Author: Ioannis Sermetziadis <se...@gmail.com>
Authored: Thu Sep 28 23:56:49 2017 +0300
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Sat Sep 30 12:39:07 2017 +0200

----------------------------------------------------------------------
 .../http/entity/mime/FormBodyPartBuilder.java   | 39 ++++++++-----------
 .../java/org/apache/http/entity/mime/MIME.java  |  7 +++-
 .../apache/http/entity/mime/MinimalField.java   | 40 +++++++++++++++++++-
 .../entity/mime/MultipartEntityBuilder.java     |  3 +-
 .../entity/mime/TestFormBodyPartBuilder.java    | 26 -------------
 .../entity/mime/TestMultipartEntityBuilder.java | 32 ++++++++++++++++
 6 files changed, 93 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/582b2806/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java
----------------------------------------------------------------------
diff --git a/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java b/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java
index 31c203a..cb3e584 100644
--- a/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java
+++ b/httpmime/src/main/java/org/apache/http/entity/mime/FormBodyPartBuilder.java
@@ -27,11 +27,14 @@
 
 package org.apache.http.entity.mime;
 
+import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.http.NameValuePair;
 import org.apache.http.entity.ContentType;
 import org.apache.http.entity.mime.content.AbstractContentBody;
 import org.apache.http.entity.mime.content.ContentBody;
+import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.Args;
 import org.apache.http.util.Asserts;
 
@@ -74,6 +77,15 @@ public class FormBodyPartBuilder {
         return this;
     }
 
+    /**
+     * @since 4.6
+     */
+    public FormBodyPartBuilder addField(final String name, final String value, final List<NameValuePair> parameters) {
+        Args.notNull(name, "Field name");
+        this.header.addField(new MinimalField(name, value, parameters));
+        return this;
+    }
+
     public FormBodyPartBuilder addField(final String name, final String value) {
         Args.notNull(name, "Field name");
         this.header.addField(new MinimalField(name, value));
@@ -101,16 +113,12 @@ public class FormBodyPartBuilder {
             headerCopy.addField(field);
         }
         if (headerCopy.getField(MIME.CONTENT_DISPOSITION) == null) {
-            final StringBuilder buffer = new StringBuilder();
-            buffer.append("form-data; name=\"");
-            buffer.append(encodeForHeader(this.name));
-            buffer.append("\"");
+            final List<NameValuePair> fieldParameters = new ArrayList<NameValuePair>();
+            fieldParameters.add(new BasicNameValuePair(MIME.FIELD_PARAM_NAME, this.name));
             if (this.body.getFilename() != null) {
-                buffer.append("; filename=\"");
-                buffer.append(encodeForHeader(this.body.getFilename()));
-                buffer.append("\"");
+                fieldParameters.add(new BasicNameValuePair(MIME.FIELD_PARAM_FILENAME, this.body.getFilename()));
             }
-            headerCopy.addField(new MinimalField(MIME.CONTENT_DISPOSITION, buffer.toString()));
+            headerCopy.addField(new MinimalField(MIME.CONTENT_DISPOSITION, "form-data", fieldParameters));
         }
         if (headerCopy.getField(MIME.CONTENT_TYPE) == null) {
             final ContentType contentType;
@@ -138,19 +146,4 @@ public class FormBodyPartBuilder {
         return new FormBodyPart(this.name, this.body, headerCopy);
     }
 
-    private static String encodeForHeader(final String headerName) {
-        if (headerName == null) {
-            return null;
-        }
-        final StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < headerName.length(); i++) {
-            final char x = headerName.charAt(i);
-            if (x == '"' || x == '\\' || x == '\r') {
-                sb.append("\\");
-            }
-            sb.append(x);
-        }
-        return sb.toString();
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/582b2806/httpmime/src/main/java/org/apache/http/entity/mime/MIME.java
----------------------------------------------------------------------
diff --git a/httpmime/src/main/java/org/apache/http/entity/mime/MIME.java b/httpmime/src/main/java/org/apache/http/entity/mime/MIME.java
index 945bd15..e4df389 100644
--- a/httpmime/src/main/java/org/apache/http/entity/mime/MIME.java
+++ b/httpmime/src/main/java/org/apache/http/entity/mime/MIME.java
@@ -27,10 +27,10 @@
 
 package org.apache.http.entity.mime;
 
-import org.apache.http.Consts;
-
 import java.nio.charset.Charset;
 
+import org.apache.http.Consts;
+
 /**
  *
  * @since 4.0
@@ -41,6 +41,9 @@ public final class MIME {
     public static final String CONTENT_TRANSFER_ENC  = "Content-Transfer-Encoding";
     public static final String CONTENT_DISPOSITION   = "Content-Disposition";
 
+    public static final String FIELD_PARAM_NAME      = "name";
+    public static final String FIELD_PARAM_FILENAME  = "filename";
+
     public static final String ENC_8BIT              = "8bit";
     public static final String ENC_BINARY            = "binary";
 

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/582b2806/httpmime/src/main/java/org/apache/http/entity/mime/MinimalField.java
----------------------------------------------------------------------
diff --git a/httpmime/src/main/java/org/apache/http/entity/mime/MinimalField.java b/httpmime/src/main/java/org/apache/http/entity/mime/MinimalField.java
index c6da877..676eba5 100644
--- a/httpmime/src/main/java/org/apache/http/entity/mime/MinimalField.java
+++ b/httpmime/src/main/java/org/apache/http/entity/mime/MinimalField.java
@@ -27,6 +27,12 @@
 
 package org.apache.http.entity.mime;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.http.NameValuePair;
+
 /**
  * Minimal MIME field.
  *
@@ -36,11 +42,27 @@ public class MinimalField {
 
     private final String name;
     private final String value;
+    private final List<NameValuePair> parameters;
 
     public MinimalField(final String name, final String value) {
         super();
         this.name = name;
         this.value = value;
+        this.parameters = Collections.emptyList();
+    }
+
+    /**
+     * @since 4.6
+     */
+    public MinimalField(final String name, final String value, final List<NameValuePair> parameters) {
+        this.name = name;
+        this.value = value;
+        this.parameters = parameters != null ?
+                Collections.unmodifiableList(new ArrayList<NameValuePair>(parameters)) : Collections.<NameValuePair>emptyList();
+    }
+
+    public MinimalField(final MinimalField from) {
+        this(from.name, from.value, from.parameters);
     }
 
     public String getName() {
@@ -48,7 +70,21 @@ public class MinimalField {
     }
 
     public String getBody() {
-        return this.value;
+        final StringBuilder sb = new StringBuilder();
+        sb.append(this.value);
+        for (int i = 0; i < this.parameters.size(); i++) {
+            final NameValuePair parameter = this.parameters.get(i);
+            sb.append("; ");
+            sb.append(parameter.getName());
+            sb.append("=\"");
+            sb.append(parameter.getValue());
+            sb.append("\"");
+        }
+        return sb.toString();
+    }
+
+    public List<NameValuePair> getParameters() {
+        return this.parameters;
     }
 
     @Override
@@ -56,7 +92,7 @@ public class MinimalField {
         final StringBuilder buffer = new StringBuilder();
         buffer.append(this.name);
         buffer.append(": ");
-        buffer.append(this.value);
+        buffer.append(this.getBody());
         return buffer.toString();
     }
 

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/582b2806/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntityBuilder.java
----------------------------------------------------------------------
diff --git a/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntityBuilder.java b/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntityBuilder.java
index 59e4ccc..d9978a8 100644
--- a/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntityBuilder.java
+++ b/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntityBuilder.java
@@ -35,6 +35,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Random;
 
+import org.apache.http.Consts;
 import org.apache.http.HttpEntity;
 import org.apache.http.NameValuePair;
 import org.apache.http.entity.ContentType;
@@ -231,7 +232,7 @@ public class MultipartEntityBuilder {
                 form = new HttpRFC6532Multipart(charsetCopy, boundaryCopy, bodyPartsCopy);
                 break;
             default:
-                form = new HttpStrictMultipart(charsetCopy, boundaryCopy, bodyPartsCopy);
+                form = new HttpStrictMultipart(Consts.ASCII, boundaryCopy, bodyPartsCopy);
         }
         return new MultipartFormEntity(form, contentTypeCopy, form.getTotalLength());
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/582b2806/httpmime/src/test/java/org/apache/http/entity/mime/TestFormBodyPartBuilder.java
----------------------------------------------------------------------
diff --git a/httpmime/src/test/java/org/apache/http/entity/mime/TestFormBodyPartBuilder.java b/httpmime/src/test/java/org/apache/http/entity/mime/TestFormBodyPartBuilder.java
index 56dd4f9..81b7e1f 100644
--- a/httpmime/src/test/java/org/apache/http/entity/mime/TestFormBodyPartBuilder.java
+++ b/httpmime/src/test/java/org/apache/http/entity/mime/TestFormBodyPartBuilder.java
@@ -27,14 +27,11 @@
 
 package org.apache.http.entity.mime;
 
-import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.util.Arrays;
 import java.util.List;
-
 import org.apache.http.entity.ContentType;
 import org.apache.http.entity.mime.content.FileBody;
-import org.apache.http.entity.mime.content.InputStreamBody;
 import org.apache.http.entity.mime.content.StringBody;
 import org.junit.Assert;
 import org.junit.Test;
@@ -61,29 +58,6 @@ public class TestFormBodyPartBuilder {
     }
 
     @Test
-    public void testCharacterStuffing() throws Exception {
-        final FormBodyPartBuilder builder = FormBodyPartBuilder.create();
-        final InputStreamBody fileBody = new InputStreamBody(new ByteArrayInputStream(
-                "hello world".getBytes("UTF-8")), "stuff_with \"quotes\" and \\slashes\\.bin");
-        final FormBodyPart bodyPart2 = builder
-                .setName("yada_with \"quotes\" and \\slashes\\")
-                .setBody(fileBody)
-                .build();
-
-        Assert.assertNotNull(bodyPart2);
-        Assert.assertEquals("yada_with \"quotes\" and \\slashes\\", bodyPart2.getName());
-        Assert.assertEquals(fileBody, bodyPart2.getBody());
-        final Header header2 = bodyPart2.getHeader();
-        Assert.assertNotNull(header2);
-        assertFields(Arrays.asList(
-                        new MinimalField("Content-Disposition", "form-data; name=\"yada_with \\\"quotes\\\" " +
-                                "and \\\\slashes\\\\\"; filename=\"stuff_with \\\"quotes\\\" and \\\\slashes\\\\.bin\""),
-                        new MinimalField("Content-Type", "application/octet-stream"),
-                        new MinimalField("Content-Transfer-Encoding", "binary")),
-                header2.getFields());
-    }
-
-    @Test
     public void testBuildBodyPartMultipleBuilds() throws Exception {
         final StringBody stringBody = new StringBody("stuff", ContentType.TEXT_PLAIN);
         final FormBodyPartBuilder builder = FormBodyPartBuilder.create();

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/582b2806/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartEntityBuilder.java
----------------------------------------------------------------------
diff --git a/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartEntityBuilder.java b/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartEntityBuilder.java
index 68a1c17..d63123b 100644
--- a/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartEntityBuilder.java
+++ b/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartEntityBuilder.java
@@ -28,12 +28,16 @@
 package org.apache.http.entity.mime;
 
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.http.Consts;
 import org.apache.http.Header;
+import org.apache.http.NameValuePair;
 import org.apache.http.entity.ContentType;
+import org.apache.http.entity.mime.content.StringBody;
 import org.apache.http.message.BasicNameValuePair;
 import org.junit.Assert;
 import org.junit.Test;
@@ -123,4 +127,32 @@ public class TestMultipartEntityBuilder {
                 contentType.getValue());
     }
 
+    @Test
+    public void testMultipartWriteTo() throws Exception {
+        final List<NameValuePair> parameters = new ArrayList<NameValuePair>();
+        parameters.add(new BasicNameValuePair(MIME.FIELD_PARAM_NAME, "test"));
+        parameters.add(new BasicNameValuePair(MIME.FIELD_PARAM_FILENAME, "hello world"));
+        final MultipartFormEntity entity = MultipartEntityBuilder.create()
+                .setStrictMode()
+                .setBoundary("xxxxxxxxxxxxxxxxxxxxxxxx")
+                .addPart(new FormBodyPartBuilder()
+                        .setName("test")
+                        .setBody(new StringBody("hello world", ContentType.TEXT_PLAIN))
+                        .addField("Content-Disposition", "multipart/form-data", parameters)
+                        .build())
+                .buildEntity();
+
+
+        final ByteArrayOutputStream out = new ByteArrayOutputStream();
+        entity.getMultipart().writeTo(out);
+        out.close();
+        Assert.assertEquals("--xxxxxxxxxxxxxxxxxxxxxxxx\r\n" +
+                "Content-Disposition: multipart/form-data; name=\"test\"; filename=\"hello world\"\r\n" +
+                "Content-Type: text/plain; charset=ISO-8859-1\r\n" +
+                "Content-Transfer-Encoding: 8bit\r\n" +
+                "\r\n" +
+                "hello world\r\n" +
+                "--xxxxxxxxxxxxxxxxxxxxxxxx--\r\n", out.toString(Consts.ASCII.name()));
+    }
+
 }