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.core5.net;
29  
30  import java.net.URI;
31  import java.nio.charset.StandardCharsets;
32  import java.util.ArrayList;
33  import java.util.List;
34  
35  import org.apache.hc.core5.http.NameValuePair;
36  import org.apache.hc.core5.http.message.BasicNameValuePair;
37  import org.junit.Assert;
38  import org.junit.Test;
39  
40  public class TestURLEncodedUtils {
41  
42      @Test
43      public void testParseURLCodedContent() throws Exception {
44          List <NameValuePair> result;
45  
46          result = parse("");
47          Assert.assertTrue(result.isEmpty());
48  
49          result = parse("Name0");
50          Assert.assertEquals(1, result.size());
51          assertNameValuePair(result.get(0), "Name0", null);
52  
53          result = parse("Name1=Value1");
54          Assert.assertEquals(1, result.size());
55          assertNameValuePair(result.get(0), "Name1", "Value1");
56  
57          result = parse("Name2=");
58          Assert.assertEquals(1, result.size());
59          assertNameValuePair(result.get(0), "Name2", "");
60  
61          result = parse("Name3");
62          Assert.assertEquals(1, result.size());
63          assertNameValuePair(result.get(0), "Name3", null);
64  
65          result = parse("Name4=Value%204%21");
66          Assert.assertEquals(1, result.size());
67          assertNameValuePair(result.get(0), "Name4", "Value 4!");
68  
69          result = parse("Name4=Value%2B4%21");
70          Assert.assertEquals(1, result.size());
71          assertNameValuePair(result.get(0), "Name4", "Value+4!");
72  
73          result = parse("Name4=Value%204%21%20%214");
74          Assert.assertEquals(1, result.size());
75          assertNameValuePair(result.get(0), "Name4", "Value 4! !4");
76  
77          result = parse("Name5=aaa&Name6=bbb");
78          Assert.assertEquals(2, result.size());
79          assertNameValuePair(result.get(0), "Name5", "aaa");
80          assertNameValuePair(result.get(1), "Name6", "bbb");
81  
82          result = parse("Name7=aaa&Name7=b%2Cb&Name7=ccc");
83          Assert.assertEquals(3, result.size());
84          assertNameValuePair(result.get(0), "Name7", "aaa");
85          assertNameValuePair(result.get(1), "Name7", "b,b");
86          assertNameValuePair(result.get(2), "Name7", "ccc");
87  
88          result = parse("Name8=xx%2C%20%20yy%20%20%2Czz");
89          Assert.assertEquals(1, result.size());
90          assertNameValuePair(result.get(0), "Name8", "xx,  yy  ,zz");
91  
92          result = parse("price=10%20%E2%82%AC");
93          Assert.assertEquals(1, result.size());
94          assertNameValuePair(result.get(0), "price", "10 \u20AC");
95      }
96  
97      @Test
98      public void testParseURLCodedContentString() throws Exception {
99          List <NameValuePair> result;
100 
101         result = parseString("");
102         Assert.assertTrue(result.isEmpty());
103 
104         result = parseString("Name0");
105         Assert.assertEquals(1, result.size());
106         assertNameValuePair(result.get(0), "Name0", null);
107 
108         result = parseString("Name1=Value1");
109         Assert.assertEquals(1, result.size());
110         assertNameValuePair(result.get(0), "Name1", "Value1");
111 
112         result = parseString("Name2=");
113         Assert.assertEquals(1, result.size());
114         assertNameValuePair(result.get(0), "Name2", "");
115 
116         result = parseString("Name3");
117         Assert.assertEquals(1, result.size());
118         assertNameValuePair(result.get(0), "Name3", null);
119 
120         result = parseString("Name4=Value%204%21");
121         Assert.assertEquals(1, result.size());
122         assertNameValuePair(result.get(0), "Name4", "Value 4!");
123 
124         result = parseString("Name4=Value%2B4%21");
125         Assert.assertEquals(1, result.size());
126         assertNameValuePair(result.get(0), "Name4", "Value+4!");
127 
128         result = parseString("Name4=Value%204%21%20%214");
129         Assert.assertEquals(1, result.size());
130         assertNameValuePair(result.get(0), "Name4", "Value 4! !4");
131 
132         result = parseString("Name5=aaa&Name6=bbb");
133         Assert.assertEquals(2, result.size());
134         assertNameValuePair(result.get(0), "Name5", "aaa");
135         assertNameValuePair(result.get(1), "Name6", "bbb");
136 
137         result = parseString("Name7=aaa&Name7=b%2Cb&Name7=ccc");
138         Assert.assertEquals(3, result.size());
139         assertNameValuePair(result.get(0), "Name7", "aaa");
140         assertNameValuePair(result.get(1), "Name7", "b,b");
141         assertNameValuePair(result.get(2), "Name7", "ccc");
142 
143         result = parseString("Name8=xx%2C%20%20yy%20%20%2Czz");
144         Assert.assertEquals(1, result.size());
145         assertNameValuePair(result.get(0), "Name8", "xx,  yy  ,zz");
146 
147         result = parseString("price=10%20%E2%82%AC");
148         Assert.assertEquals(1, result.size());
149         assertNameValuePair(result.get(0), "price", "10 \u20AC");
150     }
151 
152     @Test
153     public void testParseInvalidURLCodedContent() throws Exception {
154         List <NameValuePair> result;
155 
156         result = parse("name=%");
157         Assert.assertEquals(1, result.size());
158         assertNameValuePair(result.get(0), "name", "%");
159 
160         result = parse("name=%a");
161         Assert.assertEquals(1, result.size());
162         assertNameValuePair(result.get(0), "name", "%a");
163 
164         result = parse("name=%wa%20");
165         Assert.assertEquals(1, result.size());
166         assertNameValuePair(result.get(0), "name", "%wa ");
167     }
168 
169     private static final int SWISS_GERMAN_HELLO [] = {
170         0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
171     };
172 
173     private static final int RUSSIAN_HELLO [] = {
174         0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
175         0x432, 0x435, 0x442
176     };
177 
178     private static String constructString(final int [] unicodeChars) {
179         final StringBuilder buffer = new StringBuilder();
180         if (unicodeChars != null) {
181             for (final int unicodeChar : unicodeChars) {
182                 buffer.append((char)unicodeChar);
183             }
184         }
185         return buffer.toString();
186     }
187 
188     @Test
189     public void testParseUTF8Ampersand1String() throws Exception {
190         final String ru_hello = constructString(RUSSIAN_HELLO);
191         final String ch_hello = constructString(SWISS_GERMAN_HELLO);
192         final List <NameValuePair> parameters = new ArrayList<>();
193         parameters.add(new BasicNameValuePair("russian", ru_hello));
194         parameters.add(new BasicNameValuePair("swiss", ch_hello));
195 
196         final String s = URLEncodedUtils.format(parameters, StandardCharsets.UTF_8);
197 
198         final List <NameValuePair> result = URLEncodedUtils.parse(s, StandardCharsets.UTF_8);
199         Assert.assertEquals(2, result.size());
200         assertNameValuePair(result.get(0), "russian", ru_hello);
201         assertNameValuePair(result.get(1), "swiss", ch_hello);
202     }
203 
204     @Test
205     public void testParseUTF8Ampersand2String() throws Exception {
206         testParseUTF8String('&');
207     }
208 
209     @Test
210     public void testParseUTF8SemicolonString() throws Exception {
211         testParseUTF8String(';');
212     }
213 
214     private void testParseUTF8String(final char parameterSeparator) throws Exception {
215         final String ru_hello = constructString(RUSSIAN_HELLO);
216         final String ch_hello = constructString(SWISS_GERMAN_HELLO);
217         final List <NameValuePair> parameters = new ArrayList<>();
218         parameters.add(new BasicNameValuePair("russian", ru_hello));
219         parameters.add(new BasicNameValuePair("swiss", ch_hello));
220 
221         final String s = URLEncodedUtils.format(parameters, parameterSeparator, StandardCharsets.UTF_8);
222 
223         final List<NameValuePair> result1 = URLEncodedUtils.parse(s, StandardCharsets.UTF_8);
224         Assert.assertEquals(2, result1.size());
225         assertNameValuePair(result1.get(0), "russian", ru_hello);
226         assertNameValuePair(result1.get(1), "swiss", ch_hello);
227 
228         final List<NameValuePair> result2 = URLEncodedUtils.parse(s, StandardCharsets.UTF_8, parameterSeparator);
229         Assert.assertEquals(2, result2.size());
230         assertNameValuePair(result2.get(0), "russian", ru_hello);
231         assertNameValuePair(result2.get(1), "swiss", ch_hello);
232     }
233 
234     @Test
235     public void testEmptyQuery() throws Exception {
236         final List<NameValuePair> result = URLEncodedUtils.parse("", StandardCharsets.UTF_8);
237         Assert.assertEquals(0, result.size());
238         // [HTTPCLIENT-1889]:
239         result.add(new BasicNameValuePair("key", "value"));
240     }
241 
242     @Test
243     public void testFormat() throws Exception {
244         final List <NameValuePair> params = new ArrayList<>();
245         Assert.assertEquals(0, URLEncodedUtils.format(params, StandardCharsets.US_ASCII).length());
246 
247         params.clear();
248         params.add(new BasicNameValuePair("Name0", null));
249         Assert.assertEquals("Name0", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
250 
251         params.clear();
252         params.add(new BasicNameValuePair("Name1", "Value1"));
253         Assert.assertEquals("Name1=Value1", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
254 
255         params.clear();
256         params.add(new BasicNameValuePair("Name2", ""));
257         Assert.assertEquals("Name2=", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
258 
259         params.clear();
260         params.add(new BasicNameValuePair("Name4", "Value 4&"));
261         Assert.assertEquals("Name4=Value+4%26", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
262 
263         params.clear();
264         params.add(new BasicNameValuePair("Name4", "Value+4&"));
265         Assert.assertEquals("Name4=Value%2B4%26", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
266 
267         params.clear();
268         params.add(new BasicNameValuePair("Name4", "Value 4& =4"));
269         Assert.assertEquals("Name4=Value+4%26+%3D4", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
270 
271         params.clear();
272         params.add(new BasicNameValuePair("Name5", "aaa"));
273         params.add(new BasicNameValuePair("Name6", "bbb"));
274         Assert.assertEquals("Name5=aaa&Name6=bbb", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
275 
276         params.clear();
277         params.add(new BasicNameValuePair("Name7", "aaa"));
278         params.add(new BasicNameValuePair("Name7", "b,b"));
279         params.add(new BasicNameValuePair("Name7", "ccc"));
280         Assert.assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
281         Assert.assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, '&', StandardCharsets.US_ASCII));
282         Assert.assertEquals("Name7=aaa;Name7=b%2Cb;Name7=ccc", URLEncodedUtils.format(params, ';', StandardCharsets.US_ASCII));
283 
284         params.clear();
285         params.add(new BasicNameValuePair("Name8", "xx,  yy  ,zz"));
286         Assert.assertEquals("Name8=xx%2C++yy++%2Czz", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
287     }
288 
289     @Test
290     public void testFormatString() throws Exception { // as above, using String
291         final List <NameValuePair> params = new ArrayList<>();
292         Assert.assertEquals(0, URLEncodedUtils.format(params, StandardCharsets.US_ASCII).length());
293 
294         params.clear();
295         params.add(new BasicNameValuePair("Name0", null));
296         Assert.assertEquals("Name0", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
297 
298         params.clear();
299         params.add(new BasicNameValuePair("Name1", "Value1"));
300         Assert.assertEquals("Name1=Value1", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
301 
302         params.clear();
303         params.add(new BasicNameValuePair("Name2", ""));
304         Assert.assertEquals("Name2=", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
305 
306         params.clear();
307         params.add(new BasicNameValuePair("Name4", "Value 4&"));
308         Assert.assertEquals("Name4=Value+4%26", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
309 
310         params.clear();
311         params.add(new BasicNameValuePair("Name4", "Value+4&"));
312         Assert.assertEquals("Name4=Value%2B4%26", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
313 
314         params.clear();
315         params.add(new BasicNameValuePair("Name4", "Value 4& =4"));
316         Assert.assertEquals("Name4=Value+4%26+%3D4", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
317 
318         params.clear();
319         params.add(new BasicNameValuePair("Name5", "aaa"));
320         params.add(new BasicNameValuePair("Name6", "bbb"));
321         Assert.assertEquals("Name5=aaa&Name6=bbb", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
322 
323         params.clear();
324         params.add(new BasicNameValuePair("Name7", "aaa"));
325         params.add(new BasicNameValuePair("Name7", "b,b"));
326         params.add(new BasicNameValuePair("Name7", "ccc"));
327         Assert.assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
328 
329         params.clear();
330         params.add(new BasicNameValuePair("Name8", "xx,  yy  ,zz"));
331         Assert.assertEquals("Name8=xx%2C++yy++%2Czz", URLEncodedUtils.format(params, StandardCharsets.US_ASCII));
332     }
333 
334     private List <NameValuePair> parse (final String params) {
335         return URLEncodedUtils.parse(params, StandardCharsets.UTF_8);
336     }
337 
338     private List <NameValuePair> parseString (final String uri) throws Exception {
339         return URLEncodedUtils.parse(new URI("?"+uri), StandardCharsets.UTF_8);
340     }
341 
342     private static void assertNameValuePair (
343             final NameValuePair parameter,
344             final String expectedName,
345             final String expectedValue) {
346         Assert.assertEquals(parameter.getName(), expectedName);
347         Assert.assertEquals(parameter.getValue(), expectedValue);
348     }
349 
350 }