View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.client5.http.entity.mime;
29  
30  import java.io.ByteArrayInputStream;
31  import java.io.ByteArrayOutputStream;
32  import java.io.File;
33  import java.nio.charset.StandardCharsets;
34  import java.util.ArrayList;
35  import java.util.List;
36  
37  import org.apache.hc.core5.http.ContentType;
38  import org.apache.hc.core5.http.NameValuePair;
39  import org.apache.hc.core5.http.message.BasicNameValuePair;
40  import org.junit.Assert;
41  import org.junit.Test;
42  
43  public class TestMultipartEntityBuilder {
44  
45      @Test
46      public void testBasics() throws Exception {
47          final MultipartFormEntity entity = MultipartEntityBuilder.create().buildEntity();
48          Assert.assertNotNull(entity);
49          Assert.assertTrue(entity.getMultipart() instanceof HttpStrictMultipart);
50          Assert.assertEquals(0, entity.getMultipart().getParts().size());
51      }
52  
53      @Test
54      public void testMultipartOptions() throws Exception {
55          final MultipartFormEntity entity = MultipartEntityBuilder.create()
56                  .setBoundary("blah-blah")
57                  .setCharset(StandardCharsets.UTF_8)
58                  .setLaxMode()
59                  .buildEntity();
60          Assert.assertNotNull(entity);
61          Assert.assertTrue(entity.getMultipart() instanceof LegacyMultipart);
62          Assert.assertEquals("blah-blah", entity.getMultipart().boundary);
63          Assert.assertEquals(StandardCharsets.UTF_8, entity.getMultipart().charset);
64      }
65  
66      @Test
67      public void testAddBodyParts() throws Exception {
68          final MultipartFormEntity entity = MultipartEntityBuilder.create()
69                  .addTextBody("p1", "stuff")
70                  .addBinaryBody("p2", new File("stuff"))
71                  .addBinaryBody("p3", new byte[]{})
72                  .addBinaryBody("p4", new ByteArrayInputStream(new byte[]{}))
73                  .buildEntity();
74          Assert.assertNotNull(entity);
75          final List<MultipartPart> bodyParts = entity.getMultipart().getParts();
76          Assert.assertNotNull(bodyParts);
77          Assert.assertEquals(4, bodyParts.size());
78      }
79  
80      @Test
81      public void testMultipartCustomContentType() throws Exception {
82          final MultipartFormEntity entity = MultipartEntityBuilder.create()
83                  .setContentType(ContentType.APPLICATION_XML)
84                  .setBoundary("blah-blah")
85                  .setCharset(StandardCharsets.UTF_8)
86                  .setLaxMode()
87                  .buildEntity();
88          Assert.assertNotNull(entity);
89          Assert.assertEquals("application/xml; boundary=blah-blah; charset=UTF-8", entity.getContentType());
90      }
91  
92      @Test
93      public void testMultipartContentTypeParameter() throws Exception {
94          final MultipartFormEntity entity = MultipartEntityBuilder.create()
95                  .setContentType(ContentType.MULTIPART_FORM_DATA.withParameters(
96                          new BasicNameValuePair("boundary", "yada-yada"),
97                          new BasicNameValuePair("charset", "ascii")))
98                  .buildEntity();
99          Assert.assertNotNull(entity);
100         Assert.assertEquals("multipart/form-data; boundary=yada-yada; charset=US-ASCII", entity.getContentType());
101         Assert.assertEquals("yada-yada", entity.getMultipart().boundary);
102         Assert.assertEquals(StandardCharsets.US_ASCII, entity.getMultipart().charset);
103     }
104 
105     @Test
106     public void testMultipartCustomContentTypeParameterOverrides() throws Exception {
107         final MultipartFormEntity entity = MultipartEntityBuilder.create()
108                 .setContentType(ContentType.MULTIPART_FORM_DATA.withParameters(
109                         new BasicNameValuePair("boundary", "yada-yada"),
110                         new BasicNameValuePair("charset", "ascii"),
111                         new BasicNameValuePair("my", "stuff")))
112                 .setBoundary("blah-blah")
113                 .setCharset(StandardCharsets.UTF_8)
114                 .setLaxMode()
115                 .buildEntity();
116         Assert.assertNotNull(entity);
117         Assert.assertEquals("multipart/form-data; boundary=blah-blah; charset=UTF-8; my=stuff",
118                 entity.getContentType());
119     }
120 
121     @Test
122     public void testMultipartWriteTo() throws Exception {
123         final String helloWorld = "hello world";
124         final List<NameValuePair> parameters = new ArrayList<>();
125         parameters.add(new BasicNameValuePair(MimeConsts.FIELD_PARAM_NAME, "test"));
126         parameters.add(new BasicNameValuePair(MimeConsts.FIELD_PARAM_FILENAME, helloWorld));
127         final MultipartFormEntity entity = MultipartEntityBuilder.create()
128                 .setStrictMode()
129                 .setBoundary("xxxxxxxxxxxxxxxxxxxxxxxx")
130                 .addPart(new FormBodyPartBuilder()
131                         .setName("test")
132                         .setBody(new StringBody("hello world", ContentType.TEXT_PLAIN))
133                         .addField("Content-Disposition", "multipart/form-data", parameters)
134                         .build())
135                 .buildEntity();
136 
137 
138         final ByteArrayOutputStream out = new ByteArrayOutputStream();
139         entity.writeTo(out);
140         out.close();
141         Assert.assertEquals("--xxxxxxxxxxxxxxxxxxxxxxxx\r\n" +
142                 "Content-Disposition: multipart/form-data; name=\"test\"; filename=\"hello world\"\r\n" +
143                 "Content-Type: text/plain; charset=ISO-8859-1\r\n" +
144                 "\r\n" +
145                 helloWorld + "\r\n" +
146                 "--xxxxxxxxxxxxxxxxxxxxxxxx--\r\n", out.toString(StandardCharsets.US_ASCII.name()));
147     }
148 
149     @Test
150     public void testMultipartWriteToRFC7578Mode() throws Exception {
151         final String helloWorld = "hello \u03BA\u03CC\u03C3\u03BC\u03B5!%";
152         final List<NameValuePair> parameters = new ArrayList<>();
153         parameters.add(new BasicNameValuePair(MimeConsts.FIELD_PARAM_NAME, "test"));
154         parameters.add(new BasicNameValuePair(MimeConsts.FIELD_PARAM_FILENAME, helloWorld));
155 
156         final MultipartFormEntity entity = MultipartEntityBuilder.create()
157                 .setMode(HttpMultipartMode.EXTENDED)
158                 .setBoundary("xxxxxxxxxxxxxxxxxxxxxxxx")
159                 .addPart(new FormBodyPartBuilder()
160                         .setName("test")
161                         .setBody(new StringBody(helloWorld, ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)))
162                         .addField("Content-Disposition", "multipart/form-data", parameters)
163                         .build())
164                 .buildEntity();
165 
166         final ByteArrayOutputStream out = new ByteArrayOutputStream();
167         entity.writeTo(out);
168         out.close();
169         Assert.assertEquals("--xxxxxxxxxxxxxxxxxxxxxxxx\r\n" +
170                 "Content-Disposition: multipart/form-data; name=\"test\"; filename=\"hello%20%CE%BA%CF%8C%CF%83%CE%BC%CE%B5!%25\"\r\n" +
171                 "Content-Type: text/plain; charset=UTF-8\r\n" +
172                 "\r\n" +
173                 "hello \u00ce\u00ba\u00cf\u008c\u00cf\u0083\u00ce\u00bc\u00ce\u00b5!%\r\n" +
174                 "--xxxxxxxxxxxxxxxxxxxxxxxx--\r\n", out.toString(StandardCharsets.ISO_8859_1.name()));
175     }
176 
177     @Test
178     public void testMultipartWriteToRFC6532Mode() throws Exception {
179         final String helloWorld = "hello \u03BA\u03CC\u03C3\u03BC\u03B5!%";
180         final List<NameValuePair> parameters = new ArrayList<>();
181         parameters.add(new BasicNameValuePair(MimeConsts.FIELD_PARAM_NAME, "test"));
182         parameters.add(new BasicNameValuePair(MimeConsts.FIELD_PARAM_FILENAME, helloWorld));
183 
184         final MultipartFormEntity entity = MultipartEntityBuilder.create()
185                 .setMode(HttpMultipartMode.EXTENDED)
186                 .setContentType(ContentType.create("multipart/other"))
187                 .setBoundary("xxxxxxxxxxxxxxxxxxxxxxxx")
188                 .addPart(new FormBodyPartBuilder()
189                         .setName("test")
190                         .setBody(new StringBody(helloWorld, ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)))
191                         .addField("Content-Disposition", "multipart/form-data", parameters)
192                         .build())
193                 .buildEntity();
194 
195         final ByteArrayOutputStream out = new ByteArrayOutputStream();
196         entity.writeTo(out);
197         out.close();
198         Assert.assertEquals("--xxxxxxxxxxxxxxxxxxxxxxxx\r\n" +
199                 "Content-Disposition: multipart/form-data; name=\"test\"; " +
200                 "filename=\"hello \u00ce\u00ba\u00cf\u008c\u00cf\u0083\u00ce\u00bc\u00ce\u00b5!%\"\r\n" +
201                 "Content-Type: text/plain; charset=UTF-8\r\n" +
202                 "\r\n" +
203                 "hello \u00ce\u00ba\u00cf\u008c\u00cf\u0083\u00ce\u00bc\u00ce\u00b5!%\r\n" +
204                 "--xxxxxxxxxxxxxxxxxxxxxxxx--\r\n", out.toString(StandardCharsets.ISO_8859_1.name()));
205     }
206 
207 }