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.http.client.utils;
29  
30  import java.net.URI;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.Collections;
34  import java.util.List;
35  
36  import org.apache.http.Consts;
37  import org.apache.http.NameValuePair;
38  import org.apache.http.entity.ContentType;
39  import org.apache.http.entity.StringEntity;
40  import org.apache.http.message.BasicNameValuePair;
41  import org.apache.http.protocol.HTTP;
42  import org.hamcrest.CoreMatchers;
43  import org.junit.Assert;
44  import org.junit.Test;
45  
46  public class TestURLEncodedUtils {
47  
48      @Test
49      public void testParseURLCodedContent() throws Exception {
50          List <NameValuePair> result;
51  
52          result = parse("");
53          Assert.assertTrue(result.isEmpty());
54  
55          result = parse("Name0");
56          Assert.assertEquals(1, result.size());
57          assertNameValuePair(result.get(0), "Name0", null);
58  
59          result = parse("Name1=Value1");
60          Assert.assertEquals(1, result.size());
61          assertNameValuePair(result.get(0), "Name1", "Value1");
62  
63          result = parse("Name2=");
64          Assert.assertEquals(1, result.size());
65          assertNameValuePair(result.get(0), "Name2", "");
66  
67          result = parse("Name3");
68          Assert.assertEquals(1, result.size());
69          assertNameValuePair(result.get(0), "Name3", null);
70  
71          result = parse("Name4=Value%204%21");
72          Assert.assertEquals(1, result.size());
73          assertNameValuePair(result.get(0), "Name4", "Value 4!");
74  
75          result = parse("Name4=Value%2B4%21");
76          Assert.assertEquals(1, result.size());
77          assertNameValuePair(result.get(0), "Name4", "Value+4!");
78  
79          result = parse("Name4=Value%204%21%20%214");
80          Assert.assertEquals(1, result.size());
81          assertNameValuePair(result.get(0), "Name4", "Value 4! !4");
82  
83          result = parse("Name5=aaa&Name6=bbb");
84          Assert.assertEquals(2, result.size());
85          assertNameValuePair(result.get(0), "Name5", "aaa");
86          assertNameValuePair(result.get(1), "Name6", "bbb");
87  
88          result = parse("Name7=aaa&Name7=b%2Cb&Name7=ccc");
89          Assert.assertEquals(3, result.size());
90          assertNameValuePair(result.get(0), "Name7", "aaa");
91          assertNameValuePair(result.get(1), "Name7", "b,b");
92          assertNameValuePair(result.get(2), "Name7", "ccc");
93  
94          result = parse("Name8=xx%2C%20%20yy%20%20%2Czz");
95          Assert.assertEquals(1, result.size());
96          assertNameValuePair(result.get(0), "Name8", "xx,  yy  ,zz");
97  
98          result = parse("price=10%20%E2%82%AC");
99          Assert.assertEquals(1, result.size());
100         assertNameValuePair(result.get(0), "price", "10 \u20AC");
101 
102         result = parse("a=b\"c&d=e");
103         Assert.assertEquals(2, result.size());
104         assertNameValuePair(result.get(0), "a", "b\"c");
105         assertNameValuePair(result.get(1), "d", "e");
106     }
107 
108     @Test
109     public void testParseSegments() throws Exception {
110         Assert.assertThat(URLEncodedUtils.parsePathSegments("/this/that"),
111                 CoreMatchers.equalTo(Arrays.asList("this", "that")));
112         Assert.assertThat(URLEncodedUtils.parsePathSegments("this/that"),
113                 CoreMatchers.equalTo(Arrays.asList("this", "that")));
114         Assert.assertThat(URLEncodedUtils.parsePathSegments("this//that"),
115                 CoreMatchers.equalTo(Arrays.asList("this", "", "that")));
116         Assert.assertThat(URLEncodedUtils.parsePathSegments("this//that/"),
117                 CoreMatchers.equalTo(Arrays.asList("this", "", "that", "")));
118         Assert.assertThat(URLEncodedUtils.parsePathSegments("this//that/%2fthis%20and%20that"),
119                 CoreMatchers.equalTo(Arrays.asList("this", "", "that", "/this and that")));
120         Assert.assertThat(URLEncodedUtils.parsePathSegments("this///that//"),
121                 CoreMatchers.equalTo(Arrays.asList("this", "", "", "that", "", "")));
122         Assert.assertThat(URLEncodedUtils.parsePathSegments("/"),
123                 CoreMatchers.equalTo(Collections.singletonList("")));
124         Assert.assertThat(URLEncodedUtils.parsePathSegments(""),
125                 CoreMatchers.equalTo(Collections.<String>emptyList()));
126     }
127 
128     @Test
129     public void testFormatSegments() throws Exception {
130         Assert.assertThat(URLEncodedUtils.formatSegments("this", "that"),
131                 CoreMatchers.equalTo("/this/that"));
132         Assert.assertThat(URLEncodedUtils.formatSegments("this", "", "that"),
133                 CoreMatchers.equalTo("/this//that"));
134         Assert.assertThat(URLEncodedUtils.formatSegments("this", "", "that", "/this and that"),
135                 CoreMatchers.equalTo("/this//that/%2Fthis%20and%20that"));
136         Assert.assertThat(URLEncodedUtils.formatSegments("this", "", "", "that", "", ""),
137                 CoreMatchers.equalTo("/this///that//"));
138         Assert.assertThat(URLEncodedUtils.formatSegments(""),
139                 CoreMatchers.equalTo("/"));
140         Assert.assertThat(URLEncodedUtils.formatSegments(),
141                 CoreMatchers.equalTo(""));
142     }
143 
144     @Test
145     public void testParseURLCodedContentString() throws Exception {
146         List <NameValuePair> result;
147 
148         result = parseString("");
149         Assert.assertTrue(result.isEmpty());
150 
151         result = parseString("Name0");
152         Assert.assertEquals(1, result.size());
153         assertNameValuePair(result.get(0), "Name0", null);
154 
155         result = parseString("Name1=Value1");
156         Assert.assertEquals(1, result.size());
157         assertNameValuePair(result.get(0), "Name1", "Value1");
158 
159         result = parseString("Name2=");
160         Assert.assertEquals(1, result.size());
161         assertNameValuePair(result.get(0), "Name2", "");
162 
163         result = parseString("Name3");
164         Assert.assertEquals(1, result.size());
165         assertNameValuePair(result.get(0), "Name3", null);
166 
167         result = parseString("Name4=Value%204%21");
168         Assert.assertEquals(1, result.size());
169         assertNameValuePair(result.get(0), "Name4", "Value 4!");
170 
171         result = parseString("Name4=Value%2B4%21");
172         Assert.assertEquals(1, result.size());
173         assertNameValuePair(result.get(0), "Name4", "Value+4!");
174 
175         result = parseString("Name4=Value%204%21%20%214");
176         Assert.assertEquals(1, result.size());
177         assertNameValuePair(result.get(0), "Name4", "Value 4! !4");
178 
179         result = parseString("Name5=aaa&Name6=bbb");
180         Assert.assertEquals(2, result.size());
181         assertNameValuePair(result.get(0), "Name5", "aaa");
182         assertNameValuePair(result.get(1), "Name6", "bbb");
183 
184         result = parseString("Name7=aaa&Name7=b%2Cb&Name7=ccc");
185         Assert.assertEquals(3, result.size());
186         assertNameValuePair(result.get(0), "Name7", "aaa");
187         assertNameValuePair(result.get(1), "Name7", "b,b");
188         assertNameValuePair(result.get(2), "Name7", "ccc");
189 
190         result = parseString("Name8=xx%2C%20%20yy%20%20%2Czz");
191         Assert.assertEquals(1, result.size());
192         assertNameValuePair(result.get(0), "Name8", "xx,  yy  ,zz");
193 
194         result = parseString("price=10%20%E2%82%AC");
195         Assert.assertEquals(1, result.size());
196         assertNameValuePair(result.get(0), "price", "10 \u20AC");
197     }
198 
199     @Test
200     public void testParseInvalidURLCodedContent() throws Exception {
201         List <NameValuePair> result;
202 
203         result = parse("name=%");
204         Assert.assertEquals(1, result.size());
205         assertNameValuePair(result.get(0), "name", "%");
206 
207         result = parse("name=%a");
208         Assert.assertEquals(1, result.size());
209         assertNameValuePair(result.get(0), "name", "%a");
210 
211         result = parse("name=%wa%20");
212         Assert.assertEquals(1, result.size());
213         assertNameValuePair(result.get(0), "name", "%wa ");
214     }
215 
216     @Test
217     public void testEmptyQuery() throws Exception {
218         final List<NameValuePair> result = URLEncodedUtils.parse("", Consts.UTF_8);
219         Assert.assertEquals(0, result.size());
220         // [HTTPCLIENT-1889]:
221         result.add(new BasicNameValuePair("key", "value"));
222     }
223 
224     @Test
225     public void testParseEntity() throws Exception {
226         final StringEntity entity = new StringEntity("Name1=Value1");
227 
228         entity.setContentType(URLEncodedUtils.CONTENT_TYPE);
229         final List <NameValuePair> result = URLEncodedUtils.parse(entity);
230         Assert.assertEquals(1, result.size());
231         assertNameValuePair(result.get(0), "Name1", "Value1");
232 
233         entity.setContentType("text/test");
234         Assert.assertTrue(URLEncodedUtils.parse(entity).isEmpty());
235     }
236 
237     private static final int SWISS_GERMAN_HELLO [] = {
238         0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
239     };
240 
241     private static final int RUSSIAN_HELLO [] = {
242         0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
243         0x432, 0x435, 0x442
244     };
245 
246     private static String constructString(final int [] unicodeChars) {
247         final StringBuilder buffer = new StringBuilder();
248         if (unicodeChars != null) {
249             for (final int unicodeChar : unicodeChars) {
250                 buffer.append((char)unicodeChar);
251             }
252         }
253         return buffer.toString();
254     }
255 
256     @Test
257     public void testParseUTF8Entity() throws Exception {
258         final String ru_hello = constructString(RUSSIAN_HELLO);
259         final String ch_hello = constructString(SWISS_GERMAN_HELLO);
260         final List <NameValuePair> parameters = new ArrayList<NameValuePair>();
261         parameters.add(new BasicNameValuePair("russian", ru_hello));
262         parameters.add(new BasicNameValuePair("swiss", ch_hello));
263 
264         final String s = URLEncodedUtils.format(parameters, Consts.UTF_8);
265 
266         Assert.assertEquals("russian=%D0%92%D1%81%D0%B5%D0%BC_%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82" +
267                 "&swiss=Gr%C3%BCezi_z%C3%A4m%C3%A4", s);
268 
269         final StringEntity entity = new StringEntity(s, ContentType.create(
270                 URLEncodedUtils.CONTENT_TYPE, Consts.UTF_8));
271         final List <NameValuePair> result = URLEncodedUtils.parse(entity);
272         Assert.assertEquals(2, result.size());
273         assertNameValuePair(result.get(0), "russian", ru_hello);
274         assertNameValuePair(result.get(1), "swiss", ch_hello);
275     }
276 
277     @Test
278     public void testParseUTF8Ampersand1String() throws Exception {
279         final String ru_hello = constructString(RUSSIAN_HELLO);
280         final String ch_hello = constructString(SWISS_GERMAN_HELLO);
281         final List <NameValuePair> parameters = new ArrayList<NameValuePair>();
282         parameters.add(new BasicNameValuePair("russian", ru_hello));
283         parameters.add(new BasicNameValuePair("swiss", ch_hello));
284 
285         final String s = URLEncodedUtils.format(parameters, Consts.UTF_8);
286 
287         final List <NameValuePair> result = URLEncodedUtils.parse(s, Consts.UTF_8);
288         Assert.assertEquals(2, result.size());
289         assertNameValuePair(result.get(0), "russian", ru_hello);
290         assertNameValuePair(result.get(1), "swiss", ch_hello);
291     }
292 
293     @Test
294     public void testParseUTF8Ampersand2String() throws Exception {
295         testParseUTF8String('&');
296     }
297 
298     @Test
299     public void testParseUTF8SemicolonString() throws Exception {
300         testParseUTF8String(';');
301     }
302 
303     private void testParseUTF8String(final char parameterSeparator) throws Exception {
304         final String ru_hello = constructString(RUSSIAN_HELLO);
305         final String ch_hello = constructString(SWISS_GERMAN_HELLO);
306         final List <NameValuePair> parameters = new ArrayList<NameValuePair>();
307         parameters.add(new BasicNameValuePair("russian", ru_hello));
308         parameters.add(new BasicNameValuePair("swiss", ch_hello));
309 
310         final String s = URLEncodedUtils.format(parameters, parameterSeparator, Consts.UTF_8);
311 
312         final List <NameValuePair> result1 = URLEncodedUtils.parse(s, Consts.UTF_8);
313         Assert.assertEquals(2, result1.size());
314         assertNameValuePair(result1.get(0), "russian", ru_hello);
315         assertNameValuePair(result1.get(1), "swiss", ch_hello);
316 
317         final List <NameValuePair> result2 = URLEncodedUtils.parse(s, Consts.UTF_8, parameterSeparator);
318         Assert.assertEquals(result1, result2);
319     }
320 
321     @Test
322     public void testParseEntityDefaultContentType() throws Exception {
323         final String ch_hello = constructString(SWISS_GERMAN_HELLO);
324         final String us_hello = "hi there";
325         final List <NameValuePair> parameters = new ArrayList<NameValuePair>();
326         parameters.add(new BasicNameValuePair("english", us_hello));
327         parameters.add(new BasicNameValuePair("swiss", ch_hello));
328 
329         final String s = URLEncodedUtils.format(parameters, HTTP.DEF_CONTENT_CHARSET);
330 
331         Assert.assertEquals("english=hi+there&swiss=Gr%FCezi_z%E4m%E4", s);
332 
333         final StringEntity entity = new StringEntity(s, ContentType.create(
334                 URLEncodedUtils.CONTENT_TYPE, HTTP.DEF_CONTENT_CHARSET));
335         final List <NameValuePair> result = URLEncodedUtils.parse(entity);
336         Assert.assertEquals(2, result.size());
337         assertNameValuePair(result.get(0), "english", us_hello);
338         assertNameValuePair(result.get(1), "swiss", ch_hello);
339     }
340 
341     @Test
342     public void testIsEncoded() throws Exception {
343         final StringEntity entity = new StringEntity("...");
344 
345         entity.setContentType(URLEncodedUtils.CONTENT_TYPE);
346         Assert.assertTrue(URLEncodedUtils.isEncoded(entity));
347 
348         entity.setContentType(URLEncodedUtils.CONTENT_TYPE + "; charset=US-ASCII");
349         Assert.assertTrue(URLEncodedUtils.isEncoded(entity));
350 
351         entity.setContentType("text/test");
352         Assert.assertFalse(URLEncodedUtils.isEncoded(entity));
353     }
354 
355     @Test
356     public void testFormat() throws Exception {
357         final List <NameValuePair> params = new ArrayList <NameValuePair>();
358         Assert.assertEquals(0, URLEncodedUtils.format(params, Consts.ASCII).length());
359 
360         params.clear();
361         params.add(new BasicNameValuePair("Name0", null));
362         Assert.assertEquals("Name0", URLEncodedUtils.format(params, Consts.ASCII));
363 
364         params.clear();
365         params.add(new BasicNameValuePair("Name1", "Value1"));
366         Assert.assertEquals("Name1=Value1", URLEncodedUtils.format(params, Consts.ASCII));
367 
368         params.clear();
369         params.add(new BasicNameValuePair("Name2", ""));
370         Assert.assertEquals("Name2=", URLEncodedUtils.format(params, Consts.ASCII));
371 
372         params.clear();
373         params.add(new BasicNameValuePair("Name4", "Value 4&"));
374         Assert.assertEquals("Name4=Value+4%26", URLEncodedUtils.format(params, Consts.ASCII));
375 
376         params.clear();
377         params.add(new BasicNameValuePair("Name4", "Value+4&"));
378         Assert.assertEquals("Name4=Value%2B4%26", URLEncodedUtils.format(params, Consts.ASCII));
379 
380         params.clear();
381         params.add(new BasicNameValuePair("Name4", "Value 4& =4"));
382         Assert.assertEquals("Name4=Value+4%26+%3D4", URLEncodedUtils.format(params, Consts.ASCII));
383 
384         params.clear();
385         params.add(new BasicNameValuePair("Name5", "aaa"));
386         params.add(new BasicNameValuePair("Name6", "bbb"));
387         Assert.assertEquals("Name5=aaa&Name6=bbb", URLEncodedUtils.format(params, Consts.ASCII));
388 
389         params.clear();
390         params.add(new BasicNameValuePair("Name7", "aaa"));
391         params.add(new BasicNameValuePair("Name7", "b,b"));
392         params.add(new BasicNameValuePair("Name7", "ccc"));
393         Assert.assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, Consts.ASCII));
394         Assert.assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, '&', Consts.ASCII));
395         Assert.assertEquals("Name7=aaa;Name7=b%2Cb;Name7=ccc", URLEncodedUtils.format(params, ';', Consts.ASCII));
396 
397         params.clear();
398         params.add(new BasicNameValuePair("Name8", "xx,  yy  ,zz"));
399         Assert.assertEquals("Name8=xx%2C++yy++%2Czz", URLEncodedUtils.format(params, Consts.ASCII));
400     }
401 
402     @Test
403     public void testFormatString() throws Exception { // as above, using String
404         final List <NameValuePair> params = new ArrayList <NameValuePair>();
405         Assert.assertEquals(0, URLEncodedUtils.format(params, Consts.ASCII).length());
406 
407         params.clear();
408         params.add(new BasicNameValuePair("Name0", null));
409         Assert.assertEquals("Name0", URLEncodedUtils.format(params, Consts.ASCII));
410 
411         params.clear();
412         params.add(new BasicNameValuePair("Name1", "Value1"));
413         Assert.assertEquals("Name1=Value1", URLEncodedUtils.format(params, Consts.ASCII));
414 
415         params.clear();
416         params.add(new BasicNameValuePair("Name2", ""));
417         Assert.assertEquals("Name2=", URLEncodedUtils.format(params, Consts.ASCII));
418 
419         params.clear();
420         params.add(new BasicNameValuePair("Name4", "Value 4&"));
421         Assert.assertEquals("Name4=Value+4%26", URLEncodedUtils.format(params, Consts.ASCII));
422 
423         params.clear();
424         params.add(new BasicNameValuePair("Name4", "Value+4&"));
425         Assert.assertEquals("Name4=Value%2B4%26", URLEncodedUtils.format(params, Consts.ASCII));
426 
427         params.clear();
428         params.add(new BasicNameValuePair("Name4", "Value 4& =4"));
429         Assert.assertEquals("Name4=Value+4%26+%3D4", URLEncodedUtils.format(params, Consts.ASCII));
430 
431         params.clear();
432         params.add(new BasicNameValuePair("Name5", "aaa"));
433         params.add(new BasicNameValuePair("Name6", "bbb"));
434         Assert.assertEquals("Name5=aaa&Name6=bbb", URLEncodedUtils.format(params, Consts.ASCII));
435 
436         params.clear();
437         params.add(new BasicNameValuePair("Name7", "aaa"));
438         params.add(new BasicNameValuePair("Name7", "b,b"));
439         params.add(new BasicNameValuePair("Name7", "ccc"));
440         Assert.assertEquals("Name7=aaa&Name7=b%2Cb&Name7=ccc", URLEncodedUtils.format(params, Consts.ASCII));
441 
442         params.clear();
443         params.add(new BasicNameValuePair("Name8", "xx,  yy  ,zz"));
444         Assert.assertEquals("Name8=xx%2C++yy++%2Czz", URLEncodedUtils.format(params, Consts.ASCII));
445     }
446 
447     private List <NameValuePair> parse (final String params) {
448         return URLEncodedUtils.parse(params, Consts.UTF_8);
449     }
450 
451     private List <NameValuePair> parseString (final String uri) throws Exception {
452         return URLEncodedUtils.parse(new URI("?"+uri), Consts.UTF_8);
453     }
454 
455     private static void assertNameValuePair (
456             final NameValuePair parameter,
457             final String expectedName,
458             final String expectedValue) {
459         Assert.assertEquals(parameter.getName(), expectedName);
460         Assert.assertEquals(parameter.getValue(), expectedValue);
461     }
462 
463 }