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  package org.apache.hc.core5.net;
28  
29  import static org.hamcrest.MatcherAssert.assertThat;
30  
31  import java.net.InetAddress;
32  import java.net.URI;
33  import java.nio.charset.Charset;
34  import java.nio.charset.StandardCharsets;
35  import java.util.ArrayList;
36  import java.util.Arrays;
37  import java.util.Collections;
38  import java.util.List;
39  
40  import org.apache.hc.core5.http.HttpHost;
41  import org.apache.hc.core5.http.NameValuePair;
42  import org.apache.hc.core5.http.NameValuePairListMatcher;
43  import org.apache.hc.core5.http.URIScheme;
44  import org.apache.hc.core5.http.message.BasicNameValuePair;
45  import org.hamcrest.CoreMatchers;
46  import org.junit.jupiter.api.Assertions;
47  import org.junit.jupiter.api.Test;
48  
49  public class TestURIBuilder {
50  
51      private static final String CH_HELLO = "\u0047\u0072\u00FC\u0065\u007A\u0069\u005F\u007A\u00E4\u006D\u00E4";
52      private static final String RU_HELLO = "\u0412\u0441\u0435\u043C\u005F\u043F\u0440\u0438\u0432\u0435\u0442";
53  
54      static List<String> parsePath(final CharSequence s) {
55          return URIBuilder.parsePath(s, null);
56      }
57  
58      @Test
59      public void testParseSegments() throws Exception {
60          assertThat(parsePath("/this/that"), CoreMatchers.equalTo(Arrays.asList("this", "that")));
61          assertThat(parsePath("this/that"), CoreMatchers.equalTo(Arrays.asList("this", "that")));
62          assertThat(parsePath("this//that"), CoreMatchers.equalTo(Arrays.asList("this", "", "that")));
63          assertThat(parsePath("this//that/"), CoreMatchers.equalTo(Arrays.asList("this", "", "that", "")));
64          assertThat(parsePath("this//that/%2fthis%20and%20that"),
65                  CoreMatchers.equalTo(Arrays.asList("this", "", "that", "/this and that")));
66          assertThat(parsePath("this///that//"),
67                  CoreMatchers.equalTo(Arrays.asList("this", "", "", "that", "", "")));
68          assertThat(parsePath("/"), CoreMatchers.equalTo(Collections.singletonList("")));
69          assertThat(parsePath(""), CoreMatchers.equalTo(Collections.<String>emptyList()));
70      }
71  
72      static String formatPath(final String... pathSegments) {
73          final StringBuilder buf = new StringBuilder();
74          URIBuilder.formatPath(buf, Arrays.asList(pathSegments), false, null);
75          return buf.toString();
76      }
77  
78      @Test
79      public void testFormatSegments() throws Exception {
80          assertThat(formatPath("this", "that"), CoreMatchers.equalTo("/this/that"));
81          assertThat(formatPath("this", "", "that"), CoreMatchers.equalTo("/this//that"));
82          assertThat(formatPath("this", "", "that", "/this and that"),
83                  CoreMatchers.equalTo("/this//that/%2Fthis%20and%20that"));
84          assertThat(formatPath("this", "", "", "that", "", ""),
85                  CoreMatchers.equalTo("/this///that//"));
86          assertThat(formatPath(""), CoreMatchers.equalTo("/"));
87          assertThat(formatPath(), CoreMatchers.equalTo(""));
88      }
89  
90      static List<NameValuePair> parseQuery(final CharSequence s) {
91          return URIBuilder.parseQuery(s, null, false);
92      }
93  
94      @Test
95      public void testParseQuery() throws Exception {
96          assertThat(parseQuery(""), NameValuePairListMatcher.isEmpty());
97          assertThat(parseQuery("Name0"),
98                  NameValuePairListMatcher.equalsTo(new BasicNameValuePair("Name0", null)));
99          assertThat(parseQuery("Name1=Value1"),
100                 NameValuePairListMatcher.equalsTo(new BasicNameValuePair("Name1", "Value1")));
101         assertThat(parseQuery("Name2="),
102                 NameValuePairListMatcher.equalsTo(new BasicNameValuePair("Name2", "")));
103         assertThat(parseQuery(" Name3  "),
104                 NameValuePairListMatcher.equalsTo(new BasicNameValuePair("Name3", null)));
105         assertThat(parseQuery("Name4=Value%204%21"),
106                 NameValuePairListMatcher.equalsTo(new BasicNameValuePair("Name4", "Value 4!")));
107         assertThat(parseQuery("Name4=Value%2B4%21"),
108                 NameValuePairListMatcher.equalsTo(new BasicNameValuePair("Name4", "Value+4!")));
109         assertThat(parseQuery("Name4=Value%204%21%20%214"),
110                 NameValuePairListMatcher.equalsTo(new BasicNameValuePair("Name4", "Value 4! !4")));
111         assertThat(parseQuery("Name5=aaa&Name6=bbb"),
112                 NameValuePairListMatcher.equalsTo(
113                         new BasicNameValuePair("Name5", "aaa"),
114                         new BasicNameValuePair("Name6", "bbb")));
115         assertThat(parseQuery("Name7=aaa&Name7=b%2Cb&Name7=ccc"),
116                 NameValuePairListMatcher.equalsTo(
117                         new BasicNameValuePair("Name7", "aaa"),
118                         new BasicNameValuePair("Name7", "b,b"),
119                         new BasicNameValuePair("Name7", "ccc")));
120         assertThat(parseQuery("Name8=xx%2C%20%20yy%20%20%2Czz"),
121                 NameValuePairListMatcher.equalsTo(new BasicNameValuePair("Name8", "xx,  yy  ,zz")));
122         assertThat(parseQuery("price=10%20%E2%82%AC"),
123                 NameValuePairListMatcher.equalsTo(new BasicNameValuePair("price", "10 \u20AC")));
124         assertThat(parseQuery("a=b\"c&d=e"),
125                 NameValuePairListMatcher.equalsTo(
126                         new BasicNameValuePair("a", "b\"c"),
127                         new BasicNameValuePair("d", "e")));
128         assertThat(parseQuery("russian=" + PercentCodec.encode(RU_HELLO, StandardCharsets.UTF_8) +
129                         "&swiss=" + PercentCodec.encode(CH_HELLO, StandardCharsets.UTF_8)),
130                 NameValuePairListMatcher.equalsTo(
131                         new BasicNameValuePair("russian", RU_HELLO),
132                         new BasicNameValuePair("swiss", CH_HELLO)));
133     }
134 
135     static String formatQuery(final NameValuePair... params) {
136         final StringBuilder buf = new StringBuilder();
137         URIBuilder.formatQuery(buf, Arrays.asList(params), null, false);
138         return buf.toString();
139     }
140 
141     @Test
142     public void testFormatQuery() throws Exception {
143         assertThat(formatQuery(new BasicNameValuePair("Name0", null)), CoreMatchers.equalTo("Name0"));
144         assertThat(formatQuery(new BasicNameValuePair("Name1", "Value1")), CoreMatchers.equalTo("Name1=Value1"));
145         assertThat(formatQuery(new BasicNameValuePair("Name2", "")), CoreMatchers.equalTo("Name2="));
146         assertThat(formatQuery(new BasicNameValuePair("Name4", "Value 4&")),
147                 CoreMatchers.equalTo("Name4=Value%204%26"));
148         assertThat(formatQuery(new BasicNameValuePair("Name4", "Value+4&")),
149                 CoreMatchers.equalTo("Name4=Value%2B4%26"));
150         assertThat(formatQuery(new BasicNameValuePair("Name4", "Value 4& =4")),
151                 CoreMatchers.equalTo("Name4=Value%204%26%20%3D4"));
152         assertThat(formatQuery(
153                 new BasicNameValuePair("Name5", "aaa"),
154                 new BasicNameValuePair("Name6", "bbb")), CoreMatchers.equalTo("Name5=aaa&Name6=bbb"));
155         assertThat(formatQuery(
156                 new BasicNameValuePair("Name7", "aaa"),
157                 new BasicNameValuePair("Name7", "b,b"),
158                 new BasicNameValuePair("Name7", "ccc")
159         ), CoreMatchers.equalTo("Name7=aaa&Name7=b%2Cb&Name7=ccc"));
160         assertThat(formatQuery(new BasicNameValuePair("Name8", "xx,  yy  ,zz")),
161                 CoreMatchers.equalTo("Name8=xx%2C%20%20yy%20%20%2Czz"));
162         assertThat(formatQuery(
163                 new BasicNameValuePair("russian", RU_HELLO),
164                 new BasicNameValuePair("swiss", CH_HELLO)),
165                 CoreMatchers.equalTo("russian=" + PercentCodec.encode(RU_HELLO, StandardCharsets.UTF_8) +
166                         "&swiss=" + PercentCodec.encode(CH_HELLO, StandardCharsets.UTF_8)));
167     }
168 
169     @Test
170     public void testHierarchicalUri() throws Exception {
171         final URI uri = new URI("http", "stuff", "localhost", 80, "/some stuff", "param=stuff", "fragment");
172         final URIBuilder uribuilder = new URIBuilder(uri);
173         final URI result = uribuilder.build();
174         Assertions.assertEquals(new URI("http://stuff@localhost:80/some%20stuff?param=stuff#fragment"), result);
175     }
176 
177     @Test
178     public void testMutationToRelativeUri() throws Exception {
179         final URI uri = new URI("http://stuff@localhost:80/stuff?param=stuff#fragment");
180         final URIBuilder uribuilder = new URIBuilder(uri).setHost((String) null);
181         final URI result = uribuilder.build();
182         Assertions.assertEquals(new URI("http:///stuff?param=stuff#fragment"), result);
183     }
184 
185     @Test
186     public void testMutationRemoveFragment() throws Exception {
187         final URI uri = new URI("http://stuff@localhost:80/stuff?param=stuff#fragment");
188         final URI result = new URIBuilder(uri).setFragment(null).build();
189         Assertions.assertEquals(new URI("http://stuff@localhost:80/stuff?param=stuff"), result);
190     }
191 
192     @Test
193     public void testMutationRemoveUserInfo() throws Exception {
194         final URI uri = new URI("http://stuff@localhost:80/stuff?param=stuff#fragment");
195         final URI result = new URIBuilder(uri).setUserInfo(null).build();
196         Assertions.assertEquals(new URI("http://localhost:80/stuff?param=stuff#fragment"), result);
197     }
198 
199     @Test
200     public void testMutationRemovePort() throws Exception {
201         final URI uri = new URI("http://stuff@localhost:80/stuff?param=stuff#fragment");
202         final URI result = new URIBuilder(uri).setPort(-1).build();
203         Assertions.assertEquals(new URI("http://stuff@localhost/stuff?param=stuff#fragment"), result);
204     }
205 
206     @Test
207     public void testOpaqueUri() throws Exception {
208         final URI uri = new URI("stuff", "some-stuff", "fragment");
209         final URIBuilder uribuilder = new URIBuilder(uri);
210         final URI result = uribuilder.build();
211         Assertions.assertEquals(uri, result);
212     }
213 
214     @Test
215     public void testOpaqueUriMutation() throws Exception {
216         final URI uri = new URI("stuff", "some-stuff", "fragment");
217         final URIBuilder uribuilder = new URIBuilder(uri).setCustomQuery("param1&param2=stuff").setFragment(null);
218         Assertions.assertEquals(new URI("stuff:?param1&param2=stuff"), uribuilder.build());
219     }
220 
221     @Test
222     public void testHierarchicalUriMutation() throws Exception {
223         final URIBuilder uribuilder = new URIBuilder("/").setScheme("http").setHost("localhost").setPort(80).setPath("/stuff");
224         Assertions.assertEquals(new URI("http://localhost:80/stuff"), uribuilder.build());
225     }
226 
227     @Test
228    public void testLocalhost() throws Exception {
229        // Check that the URI generated by URI builder agrees with that generated by using URI directly
230        final String scheme="https";
231        final InetAddress host=InetAddress.getLocalHost();
232        final String specials="/abcd!$&*()_-+.,=:;'~@[]?<>|#^%\"{}\\\u00a3`\u00ac\u00a6xyz"; // N.B. excludes space
233        final URI uri = new URI(scheme, specials, host.getHostAddress(), 80, specials, specials, specials);
234 
235        final URI bld = URIBuilder.localhost()
236                .setScheme(scheme)
237                .setUserInfo(specials)
238                .setPath(specials)
239                .setCustomQuery(specials)
240                .setFragment(specials)
241                .build();
242 
243        Assertions.assertEquals(uri.getHost(), bld.getHost());
244 
245        Assertions.assertEquals(uri.getUserInfo(), bld.getUserInfo());
246 
247        Assertions.assertEquals(uri.getPath(), bld.getPath());
248 
249        Assertions.assertEquals(uri.getQuery(), bld.getQuery());
250 
251        Assertions.assertEquals(uri.getFragment(), bld.getFragment());
252    }
253 
254     @Test
255    public void testLoopbackAddress() throws Exception {
256        // Check that the URI generated by URI builder agrees with that generated by using URI directly
257        final String scheme="https";
258        final InetAddress host=InetAddress.getLoopbackAddress();
259        final String specials="/abcd!$&*()_-+.,=:;'~@[]?<>|#^%\"{}\\\u00a3`\u00ac\u00a6xyz"; // N.B. excludes space
260        final URI uri = new URI(scheme, specials, host.getHostAddress(), 80, specials, specials, specials);
261 
262        final URI bld = URIBuilder.loopbackAddress()
263                .setScheme(scheme)
264                .setUserInfo(specials)
265                .setPath(specials)
266                .setCustomQuery(specials)
267                .setFragment(specials)
268                .build();
269 
270        Assertions.assertEquals(uri.getHost(), bld.getHost());
271 
272        Assertions.assertEquals(uri.getUserInfo(), bld.getUserInfo());
273 
274        Assertions.assertEquals(uri.getPath(), bld.getPath());
275 
276        Assertions.assertEquals(uri.getQuery(), bld.getQuery());
277 
278        Assertions.assertEquals(uri.getFragment(), bld.getFragment());
279    }
280 
281     @Test
282     public void testEmpty() throws Exception {
283         final URIBuilder uribuilder = new URIBuilder();
284         final URI result = uribuilder.build();
285         Assertions.assertEquals(new URI(""), result);
286     }
287 
288     @Test
289     public void testEmptyPath() throws Exception {
290         final URIBuilder uribuilder = new URIBuilder("http://thathost");
291         Assertions.assertTrue(uribuilder.isPathEmpty());
292     }
293 
294     @Test
295     public void testRemoveParameter() throws Exception {
296         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff&blah&blah", null);
297         final URIBuilder uribuilder = new URIBuilder(uri);
298         Assertions.assertFalse(uribuilder.isQueryEmpty());
299 
300         Assertions.assertThrows(NullPointerException.class, () -> uribuilder.removeParameter(null));
301 
302         uribuilder.removeParameter("DoesNotExist");
303         Assertions.assertEquals("stuff", uribuilder.getFirstQueryParam("param").getValue());
304         Assertions.assertNull(uribuilder.getFirstQueryParam("blah").getValue());
305 
306         uribuilder.removeParameter("blah");
307         Assertions.assertEquals("stuff", uribuilder.getFirstQueryParam("param").getValue());
308         Assertions.assertNull(uribuilder.getFirstQueryParam("blah"));
309 
310         uribuilder.removeParameter("param");
311         Assertions.assertNull(uribuilder.getFirstQueryParam("param"));
312         Assertions.assertTrue(uribuilder.isQueryEmpty());
313 
314         uribuilder.removeParameter("AlreadyEmpty");
315         Assertions.assertTrue(uribuilder.isQueryEmpty());
316         Assertions.assertEquals(new URI("http://localhost:80/"), uribuilder.build());
317     }
318 
319     @Test
320     public void testRemoveQuery() throws Exception {
321         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff", null);
322         final URIBuilder uribuilder = new URIBuilder(uri).removeQuery();
323         final URI result = uribuilder.build();
324         Assertions.assertEquals(new URI("http://localhost:80/"), result);
325     }
326 
327     @Test
328     public void testSetAuthorityFromNamedEndpointHost() throws Exception {
329         final Host host = Host.create("localhost:88");
330         final URIBuilder uribuilder = new URIBuilder().setScheme(URIScheme.HTTP.id).setAuthority(host);
331         // Check builder
332         Assertions.assertNull(uribuilder.getUserInfo());
333         Assertions.assertEquals(host.getHostName(), uribuilder.getAuthority().getHostName());
334         Assertions.assertEquals(host.getHostName(), uribuilder.getHost());
335         // Check result
336         final URI result = uribuilder.build();
337         Assertions.assertEquals(host.getHostName(), result.getHost());
338         Assertions.assertEquals(host.getPort(), result.getPort());
339         Assertions.assertEquals(new URI("http://localhost:88"), result);
340     }
341 
342     @Test
343     public void testSetAuthorityFromNamedEndpointHttpHost() throws Exception {
344         final HttpHost httpHost = HttpHost.create("localhost:88");
345         final URIBuilder uribuilder = new URIBuilder().setScheme(URIScheme.HTTP.id).setAuthority(httpHost);
346         // Check builder
347         Assertions.assertNull(uribuilder.getUserInfo());
348         Assertions.assertEquals(httpHost.getHostName(), uribuilder.getAuthority().getHostName());
349         Assertions.assertEquals(httpHost.getHostName(), uribuilder.getHost());
350         // Check result
351         final URI result = uribuilder.build();
352         Assertions.assertEquals(httpHost.getHostName(), result.getHost());
353         Assertions.assertEquals(httpHost.getPort(), result.getPort());
354         Assertions.assertEquals(new URI("http://localhost:88"), result);
355     }
356 
357     @Test
358     public void testSetAuthorityFromURIAuthority() throws Exception {
359         final URIAuthority authority = URIAuthority.create("u:p@localhost:88");
360         final URIBuilder uribuilder = new URIBuilder().setScheme(URIScheme.HTTP.id).setAuthority(authority);
361         // Check builder
362         Assertions.assertEquals(authority.getUserInfo(), uribuilder.getAuthority().getUserInfo());
363         Assertions.assertEquals(authority.getHostName(), uribuilder.getAuthority().getHostName());
364         Assertions.assertEquals(authority.getHostName(), uribuilder.getHost());
365         // Check result
366         final URI result = uribuilder.build();
367         Assertions.assertEquals(authority.getUserInfo(), result.getUserInfo());
368         Assertions.assertEquals(authority.getHostName(), result.getHost());
369         Assertions.assertEquals(authority.getPort(), result.getPort());
370         Assertions.assertEquals(authority.toString(), result.getAuthority());
371         Assertions.assertEquals(new URI("http://u:p@localhost:88"), result);
372     }
373 
374     @Test
375     public void testSetParameter() throws Exception {
376         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff&blah&blah", null);
377         final URIBuilder uribuilder = new URIBuilder(uri).setParameter("param", "some other stuff")
378                 .setParameter("blah", "blah")
379                 .setParameter("blah", "blah2");
380         final URI result = uribuilder.build();
381         Assertions.assertEquals(new URI("http://localhost:80/?param=some%20other%20stuff&blah=blah2"), result);
382     }
383 
384     @Test
385     public void testGetFirstNamedParameter() throws Exception {
386         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff&blah&blah", null);
387         URIBuilder uribuilder = new URIBuilder(uri).setParameter("param", "some other stuff")
388             .setParameter("blah", "blah");
389         Assertions.assertEquals("some other stuff", uribuilder.getFirstQueryParam("param").getValue());
390         Assertions.assertEquals("blah", uribuilder.getFirstQueryParam("blah").getValue());
391         Assertions.assertNull(uribuilder.getFirstQueryParam("DoesNotExist"));
392         //
393         uribuilder = new URIBuilder("http://localhost:80/?param=some%20other%20stuff&blah=blah&blah=blah2");
394         Assertions.assertEquals("blah", uribuilder.getFirstQueryParam("blah").getValue());
395         uribuilder.removeQuery();
396         Assertions.assertNull(uribuilder.getFirstQueryParam("param"));
397     }
398 
399     @Test
400     public void testSetParametersWithEmptyArrayArg() throws Exception {
401         final URI uri = new URI("http", null, "localhost", 80, "/test", "param=test", null);
402         final URIBuilder uribuilder = new URIBuilder(uri).setParameters();
403         final URI result = uribuilder.build();
404         Assertions.assertEquals(new URI("http://localhost:80/test"), result);
405     }
406 
407     @Test
408     public void testSetParametersWithNullArrayArg() throws Exception {
409         final URI uri = new URI("http", null, "localhost", 80, "/test", "param=test", null);
410         final URIBuilder uribuilder = new URIBuilder(uri).setParameters((NameValuePair[]) null);
411         final URI result = uribuilder.build();
412         Assertions.assertEquals(new URI("http://localhost:80/test"), result);
413     }
414 
415     @Test
416     public void testSetParametersWithEmptyList() throws Exception {
417         final URI uri = new URI("http", null, "localhost", 80, "/test", "param=test", null);
418         final URIBuilder uribuilder = new URIBuilder(uri).setParameters(Collections.emptyList());
419         final URI result = uribuilder.build();
420         Assertions.assertEquals(new URI("http://localhost:80/test"), result);
421     }
422 
423     @Test
424     public void testSetParametersWithNullList() throws Exception {
425         final URI uri = new URI("http", null, "localhost", 80, "/test", "param=test", null);
426         final URIBuilder uribuilder = new URIBuilder(uri).setParameters((List<NameValuePair>) null);
427         final URI result = uribuilder.build();
428         Assertions.assertEquals(new URI("http://localhost:80/test"), result);
429     }
430 
431     @Test
432     public void testParameterWithSpecialChar() throws Exception {
433         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff", null);
434         final URIBuilder uribuilder = new URIBuilder(uri).addParameter("param", "1 + 1 = 2")
435             .addParameter("param", "blah&blah");
436         final URI result = uribuilder.build();
437         Assertions.assertEquals(new URI("http://localhost:80/?param=stuff&param=1%20%2B%201%20%3D%202&" +
438                 "param=blah%26blah"), result);
439     }
440 
441     @Test
442     public void testAddParameter() throws Exception {
443         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff&blah&blah", null);
444         final URIBuilder uribuilder = new URIBuilder(uri).addParameter("param", "some other stuff")
445             .addParameter("blah", "blah");
446         final URI result = uribuilder.build();
447         Assertions.assertEquals(new URI("http://localhost:80/?param=stuff&blah&blah&" +
448                 "param=some%20other%20stuff&blah=blah"), result);
449     }
450 
451     @Test
452     public void testQueryEncoding() throws Exception {
453         final URI uri1 = new URI("https://somehost.com/stuff?client_id=1234567890" +
454                 "&redirect_uri=https%3A%2F%2Fsomehost.com%2Fblah%20blah%2F");
455         final URI uri2 = new URIBuilder("https://somehost.com/stuff")
456             .addParameter("client_id","1234567890")
457             .addParameter("redirect_uri","https://somehost.com/blah blah/").build();
458         Assertions.assertEquals(uri1, uri2);
459     }
460 
461     @Test
462     public void testQueryAndParameterEncoding() throws Exception {
463         final URI uri1 = new URI("https://somehost.com/stuff?param1=12345&param2=67890");
464         final URI uri2 = new URIBuilder("https://somehost.com/stuff")
465             .setCustomQuery("this&that")
466             .addParameter("param1","12345")
467             .addParameter("param2","67890").build();
468         Assertions.assertEquals(uri1, uri2);
469     }
470 
471     @Test
472     public void testPathEncoding() throws Exception {
473         final URI uri1 = new URI("https://somehost.com/some%20path%20with%20blanks/");
474         final URI uri2 = new URIBuilder()
475             .setScheme("https")
476             .setHost("somehost.com")
477             .setPath("/some path with blanks/")
478             .build();
479         Assertions.assertEquals(uri1, uri2);
480     }
481 
482     @Test
483     public void testAgainstURI() throws Exception {
484         // Check that the URI generated by URI builder agrees with that generated by using URI directly
485         final String scheme="https";
486         final String host="localhost";
487         final String specials="/abcd!$&*()_-+.,=:;'~@[]?<>|#^%\"{}\\\u00a3`\u00ac\u00a6xyz"; // N.B. excludes space
488         final URI uri = new URI(scheme, specials, host, 80, specials, specials, specials);
489 
490         final URI bld = new URIBuilder()
491                 .setScheme(scheme)
492                 .setHost(host)
493                 .setUserInfo(specials)
494                 .setPath(specials)
495                 .setCustomQuery(specials)
496                 .setFragment(specials)
497                 .build();
498 
499         Assertions.assertEquals(uri.getHost(), bld.getHost());
500 
501         Assertions.assertEquals(uri.getUserInfo(), bld.getUserInfo());
502 
503         Assertions.assertEquals(uri.getPath(), bld.getPath());
504 
505         Assertions.assertEquals(uri.getQuery(), bld.getQuery());
506 
507         Assertions.assertEquals(uri.getFragment(), bld.getFragment());
508 
509     }
510 
511     @Test
512     public void testBuildAddParametersUTF8() throws Exception {
513         assertAddParameters(StandardCharsets.UTF_8);
514     }
515 
516     @Test
517     public void testBuildAddParametersISO88591() throws Exception {
518         assertAddParameters(StandardCharsets.ISO_8859_1);
519     }
520 
521     public void assertAddParameters(final Charset charset) throws Exception {
522         final URI uri = new URIBuilder("https://somehost.com/stuff")
523                 .setCharset(charset)
524                 .addParameters(createParameterList()).build();
525 
526         assertBuild(charset, uri);
527         // null addParameters
528         final URI uri2 = new URIBuilder("https://somehost.com/stuff")
529                 .setCharset(charset)
530                 .addParameters(null).build();
531 
532         Assertions.assertEquals("https://somehost.com/stuff", uri2.toString());
533     }
534 
535     @Test
536     public void testBuildSetParametersUTF8() throws Exception {
537         assertSetParameters(StandardCharsets.UTF_8);
538     }
539 
540     @Test
541     public void testBuildSetParametersISO88591() throws Exception {
542         assertSetParameters(StandardCharsets.ISO_8859_1);
543     }
544 
545     public void assertSetParameters(final Charset charset) throws Exception {
546         final URI uri = new URIBuilder("https://somehost.com/stuff")
547                 .setCharset(charset)
548                 .setParameters(createParameterList()).build();
549 
550         assertBuild(charset, uri);
551     }
552 
553     public void assertBuild(final Charset charset, final URI uri) throws Exception {
554         final String encodedData1 = PercentCodec.encode("\"1\u00aa position\"", charset);
555         final String encodedData2 = PercentCodec.encode("Jos\u00e9 Abra\u00e3o", charset);
556 
557         final String uriExpected = String.format("https://somehost.com/stuff?parameter1=value1&parameter2=%s&parameter3=%s", encodedData1, encodedData2);
558 
559         Assertions.assertEquals(uriExpected, uri.toString());
560     }
561 
562     private List<NameValuePair> createParameterList() {
563         final List<NameValuePair> parameters = new ArrayList<>();
564         parameters.add(new BasicNameValuePair("parameter1", "value1"));
565         parameters.add(new BasicNameValuePair("parameter2", "\"1\u00aa position\""));
566         parameters.add(new BasicNameValuePair("parameter3", "Jos\u00e9 Abra\u00e3o"));
567         return parameters;
568     }
569 
570     @Test
571     public void testMalformedPath() throws Exception {
572         final String path = "@notexample.com/mypath";
573         final URI uri = new URIBuilder(path).setHost("example.com").build();
574         Assertions.assertEquals("example.com", uri.getHost());
575     }
576 
577     @Test
578     public void testRelativePath() throws Exception {
579         final URI uri = new URIBuilder("./mypath").build();
580         Assertions.assertEquals(new URI("./mypath"), uri);
581     }
582 
583     @Test
584     public void testRelativePathWithAuthority() throws Exception {
585         final URI uri = new URIBuilder("./mypath").setHost("somehost").setScheme("http").build();
586         Assertions.assertEquals(new URI("http://somehost/./mypath"), uri);
587     }
588 
589     @Test
590     public void testTolerateNullInput() throws Exception {
591         assertThat(new URIBuilder()
592                         .setScheme(null)
593                         .setHost("localhost")
594                         .setUserInfo(null)
595                         .setPort(8443)
596                         .setPath(null)
597                         .setCustomQuery(null)
598                         .setFragment(null)
599                         .build(),
600                 CoreMatchers.equalTo(URI.create("//localhost:8443")));
601     }
602 
603     @Test
604     public void testTolerateBlankInput() throws Exception {
605         assertThat(new URIBuilder()
606                         .setScheme("")
607                         .setHost("localhost")
608                         .setUserInfo("")
609                         .setPort(8443)
610                         .setPath("")
611                         .setPath("")
612                         .setCustomQuery("")
613                         .setFragment("")
614                         .build(),
615                 CoreMatchers.equalTo(URI.create("//localhost:8443")));
616     }
617 
618     @Test
619     public void testHttpHost() throws Exception {
620         final HttpHost httpHost = new HttpHost("http", "example.com", 1234);
621         final URIBuilder uribuilder = new URIBuilder();
622         uribuilder.setHttpHost(httpHost);
623         Assertions.assertEquals(URI.create("http://example.com:1234"), uribuilder.build());
624     }
625 
626     @Test
627     public void testSetHostWithReservedChars() throws Exception {
628         final URIBuilder uribuilder = new URIBuilder();
629         uribuilder.setScheme("http").setHost("!example!.com");
630         Assertions.assertEquals(URI.create("http://%21example%21.com"), uribuilder.build());
631     }
632 
633     @Test
634     public void testGetHostWithReservedChars() throws Exception {
635         final URIBuilder uribuilder = new URIBuilder("http://someuser%21@%21example%21.com/");
636         Assertions.assertEquals("!example!.com", uribuilder.getHost());
637         Assertions.assertEquals("someuser!", uribuilder.getUserInfo());
638     }
639 
640     @Test
641     public void testMultipleLeadingPathSlashes() throws Exception {
642         final URI uri = new URIBuilder()
643                 .setScheme("ftp")
644                 .setHost("somehost")
645                 .setPath("//blah//blah")
646                 .build();
647         assertThat(uri, CoreMatchers.equalTo(URI.create("ftp://somehost//blah//blah")));
648     }
649 
650     @Test
651     public void testNoAuthorityAndPath() throws Exception {
652         final URI uri = new URIBuilder()
653                 .setScheme("file")
654                 .setPath("/blah")
655                 .build();
656         assertThat(uri, CoreMatchers.equalTo(URI.create("file:/blah")));
657     }
658 
659     @Test
660     public void testSetPathSegmentList() throws Exception {
661         final URI uri = new URIBuilder()
662             .setScheme("https")
663             .setHost("somehost")
664             .setPathSegments(Arrays.asList("api", "products"))
665             .build();
666         assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/api/products")));
667     }
668 
669     @Test
670     public void testSetPathSegmentsVarargs() throws Exception {
671         final URI uri = new URIBuilder()
672             .setScheme("https")
673             .setHost("somehost")
674             .setPathSegments("api", "products")
675             .build();
676         assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/api/products")));
677     }
678 
679     @Test
680     public void testSetPathSegmentsRootlessList() throws Exception {
681         final URI uri = new URIBuilder()
682             .setScheme("file")
683             .setPathSegmentsRootless(Arrays.asList("dir", "foo"))
684             .build();
685         assertThat(uri, CoreMatchers.equalTo(URI.create("file:dir/foo")));
686     }
687 
688     @Test
689     public void testSetPathSegmentsRootlessVarargs() throws Exception {
690         final URI uri = new URIBuilder()
691             .setScheme("file")
692             .setPathSegmentsRootless("dir", "foo")
693             .build();
694         assertThat(uri, CoreMatchers.equalTo(URI.create("file:dir/foo")));
695     }
696 
697     @Test
698     public void testAppendToExistingPath() throws Exception {
699         final URI uri = new URIBuilder()
700             .setScheme("https")
701             .setHost("somehost")
702             .setPath("api")
703             .appendPath("v1/resources")
704             .appendPath("idA")
705             .build();
706         assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/api/v1/resources/idA")));
707     }
708 
709     @Test
710     public void testAppendToNonExistingPath() throws Exception {
711         final URI uri = new URIBuilder()
712             .setScheme("https")
713             .setHost("somehost")
714             .appendPath("api/v2/customers")
715             .appendPath("idA")
716             .build();
717         assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/api/v2/customers/idA")));
718     }
719 
720     @Test
721     public void testAppendNullToExistingPath() throws Exception {
722         final URI uri = new URIBuilder()
723             .setScheme("https")
724             .setHost("somehost")
725             .setPath("api")
726             .appendPath(null)
727             .build();
728         assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/api")));
729     }
730 
731     @Test
732     public void testAppendNullToNonExistingPath() throws Exception {
733         final URI uri = new URIBuilder()
734             .setScheme("https")
735             .setHost("somehost")
736             .appendPath(null)
737             .build();
738         assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost")));
739     }
740 
741     @Test
742     public void testAppendSegmentsVarargsToExistingPath() throws Exception {
743         final URI uri = new URIBuilder()
744             .setScheme("https")
745             .setHost("myhost")
746             .setPath("api")
747             .appendPathSegments("v3", "products")
748             .appendPathSegments("idA")
749             .build();
750         assertThat(uri, CoreMatchers.equalTo(URI.create("https://myhost/api/v3/products/idA")));
751     }
752 
753     @Test
754     public void testAppendSegmentsVarargsToNonExistingPath() throws Exception {
755         final URI uri = new URIBuilder()
756             .setScheme("https")
757             .setHost("somehost")
758             .appendPathSegments("api", "v2", "customers")
759             .appendPathSegments("idA")
760             .build();
761         assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/api/v2/customers/idA")));
762     }
763 
764     @Test
765     public void testAppendNullSegmentsVarargs() throws Exception {
766         final String pathSegment = null;
767         final URI uri = new URIBuilder()
768             .setScheme("https")
769             .setHost("somehost")
770             .appendPathSegments(pathSegment)
771             .build();
772         assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/")));
773     }
774 
775     @Test
776     public void testAppendSegmentsListToExistingPath() throws Exception {
777         final URI uri = new URIBuilder()
778             .setScheme("http")
779             .setHost("myhost")
780             .setPath("api")
781             .appendPathSegments(Arrays.asList("v3", "products"))
782             .build();
783         assertThat(uri, CoreMatchers.equalTo(URI.create("http://myhost/api/v3/products")));
784     }
785 
786     @Test
787     public void testAppendSegmentsListToNonExistingPath() throws Exception {
788         final URI uri = new URIBuilder()
789             .setScheme("http")
790             .setHost("myhost")
791             .appendPathSegments(Arrays.asList("api", "v3", "customers"))
792             .build();
793         assertThat(uri, CoreMatchers.equalTo(URI.create("http://myhost/api/v3/customers")));
794     }
795 
796     @Test
797     public void testAppendNullSegmentsList() throws Exception {
798         final List<String> pathSegments = null;
799         final URI uri = new URIBuilder()
800             .setScheme("http")
801             .setHost("myhost")
802             .appendPathSegments(pathSegments)
803             .build();
804         assertThat(uri, CoreMatchers.equalTo(URI.create("http://myhost")));
805     }
806 
807     @Test
808     public void testNoAuthorityAndPathSegments() throws Exception {
809         final URI uri = new URIBuilder()
810                 .setScheme("file")
811                 .setPathSegments("this", "that")
812                 .build();
813         assertThat(uri, CoreMatchers.equalTo(URI.create("file:/this/that")));
814     }
815 
816     @Test
817     public void testNoAuthorityAndRootlessPath() throws Exception {
818         final URI uri = new URIBuilder()
819                 .setScheme("file")
820                 .setPath("blah")
821                 .build();
822         assertThat(uri, CoreMatchers.equalTo(URI.create("file:blah")));
823     }
824 
825     @Test
826     public void testNoAuthorityAndRootlessPathSegments() throws Exception {
827         final URI uri = new URIBuilder()
828                 .setScheme("file")
829                 .setPathSegmentsRootless("this", "that")
830                 .build();
831         assertThat(uri, CoreMatchers.equalTo(URI.create("file:this/that")));
832     }
833 
834     @Test
835     public void testOpaque() throws Exception {
836         final URIBuilder uriBuilder = new URIBuilder("http://host.com");
837         final URI uri = uriBuilder.build();
838         assertThat(uriBuilder.isOpaque(), CoreMatchers.equalTo(uri.isOpaque()));
839     }
840 
841     @Test
842     public void testAddParameterEncodingEquivalence() throws Exception {
843         final URI uri = new URI("http", null, "localhost", 80, "/",
844                 "param=stuff with spaces", null);
845         final URIBuilder uribuilder = new URIBuilder().setScheme("http").setHost("localhost").setPort(80).setPath("/").addParameter(
846                 "param", "stuff with spaces");
847         final URI result = uribuilder.build();
848         Assertions.assertEquals(uri, result);
849     }
850 
851     @Test
852     public void testSchemeSpecificPartParametersNull() throws Exception {
853        final URIBuilder uribuilder = new URIBuilder("http://host.com").setParameter("par", "parvalue")
854                .setSchemeSpecificPart("", (NameValuePair)null);
855        Assertions.assertEquals(new URI("http://host.com?par=parvalue"), uribuilder.build());
856     }
857 
858     @Test
859     public void testSchemeSpecificPartSetGet() throws Exception {
860        final URIBuilder uribuilder = new URIBuilder().setSchemeSpecificPart("specificpart");
861        Assertions.assertEquals("specificpart", uribuilder.getSchemeSpecificPart());
862     }
863 
864     /** Common use case: mailto: scheme. See https://tools.ietf.org/html/rfc6068#section-2 */
865     @Test
866     public void testSchemeSpecificPartNameValuePairByRFC6068Sample() throws Exception {
867        final URIBuilder uribuilder = new URIBuilder().setScheme("mailto")
868                .setSchemeSpecificPart("my@email.server", new BasicNameValuePair("subject", "mail subject"));
869        final String result = uribuilder.build().toString();
870        Assertions.assertTrue(result.contains("my@email.server"), "mail address as scheme specific part expected");
871        Assertions.assertTrue(result.contains("mail%20subject"), "correct parameter encoding expected for that scheme");
872     }
873 
874     /** Common use case: mailto: scheme. See https://tools.ietf.org/html/rfc6068#section-2 */
875     @Test
876     public void testSchemeSpecificPartNameValuePairListByRFC6068Sample() throws Exception {
877         final List<NameValuePair> parameters = new ArrayList<>();
878         parameters.add(new BasicNameValuePair("subject", "mail subject"));
879 
880        final URIBuilder uribuilder = new URIBuilder().setScheme("mailto").setSchemeSpecificPart("my@email.server", parameters);
881        final String result = uribuilder.build().toString();
882        Assertions.assertTrue(result.contains("my@email.server"), "mail address as scheme specific part expected");
883        Assertions.assertTrue(result.contains("mail%20subject"), "correct parameter encoding expected for that scheme");
884     }
885 
886     @Test
887     public void testNormalizeSyntax() throws Exception {
888         Assertions.assertEquals("example://a/b/c/%7Bfoo%7D",
889                 new URIBuilder("eXAMPLE://a/./b/../b/%63/%7bfoo%7d").normalizeSyntax().build().toASCIIString());
890         Assertions.assertEquals("http://www.example.com/%3C",
891                 new URIBuilder("http://www.example.com/%3c").normalizeSyntax().build().toASCIIString());
892         Assertions.assertEquals("http://www.example.com/",
893                 new URIBuilder("HTTP://www.EXAMPLE.com/").normalizeSyntax().build().toASCIIString());
894         Assertions.assertEquals("http://www.example.com/a%2F",
895                 new URIBuilder("http://www.example.com/a%2f").normalizeSyntax().build().toASCIIString());
896         Assertions.assertEquals("http://www.example.com/?a%2F",
897                 new URIBuilder("http://www.example.com/?a%2f").normalizeSyntax().build().toASCIIString());
898         Assertions.assertEquals("http://www.example.com/?q=%26",
899                 new URIBuilder("http://www.example.com/?q=%26").normalizeSyntax().build().toASCIIString());
900         Assertions.assertEquals("http://www.example.com/%23?q=%26",
901                 new URIBuilder("http://www.example.com/%23?q=%26").normalizeSyntax().build().toASCIIString());
902         Assertions.assertEquals("http://www.example.com/blah-%28%20-blah-%20%26%20-blah-%20%29-blah/",
903                 new URIBuilder("http://www.example.com/blah-%28%20-blah-%20&%20-blah-%20)-blah/").normalizeSyntax().build().toASCIIString());
904         Assertions.assertEquals("../../.././",
905                 new URIBuilder("../../.././").normalizeSyntax().build().toASCIIString());
906         Assertions.assertEquals("file:../../.././",
907                 new URIBuilder("file:../../.././").normalizeSyntax().build().toASCIIString());
908         Assertions.assertEquals("http://host/",
909                 new URIBuilder("http://host/../../.././").normalizeSyntax().build().toASCIIString());
910         Assertions.assertEquals("http:/",
911                 new URIBuilder("http:///../../.././").normalizeSyntax().build().toASCIIString());
912     }
913 
914     @Test
915     public void testIpv6Host() throws Exception {
916         final URIBuilder builder = new URIBuilder("https://[::1]:432/path");
917         final URI uri = builder.build();
918         Assertions.assertEquals(432, builder.getPort());
919         Assertions.assertEquals(432, uri.getPort());
920         Assertions.assertEquals("https", builder.getScheme());
921         Assertions.assertEquals("https", uri.getScheme());
922         Assertions.assertEquals("::1", builder.getHost());
923         Assertions.assertEquals("[::1]", uri.getHost());
924         Assertions.assertEquals("/path", builder.getPath());
925         Assertions.assertEquals("/path", uri.getPath());
926     }
927 
928     @Test
929     public void testIpv6HostWithPortUpdate() throws Exception {
930         // Updating the port clears URIBuilder.encodedSchemeSpecificPart
931         // and bypasses the fast/simple path which preserves input.
932         final URIBuilder builder = new URIBuilder("https://[::1]:432/path").setPort(123);
933         final URI uri = builder.build();
934         Assertions.assertEquals(123, builder.getPort());
935         Assertions.assertEquals(123, uri.getPort());
936         Assertions.assertEquals("https", builder.getScheme());
937         Assertions.assertEquals("https", uri.getScheme());
938         Assertions.assertEquals("::1", builder.getHost());
939         Assertions.assertEquals("[::1]", uri.getHost());
940         Assertions.assertEquals("/path", builder.getPath());
941         Assertions.assertEquals("/path", uri.getPath());
942     }
943 
944     @Test
945     public void testBuilderWithUnbracketedIpv6Host() throws Exception {
946         final URIBuilder builder = new URIBuilder().setScheme("https").setHost("::1").setPort(443).setPath("/path");
947         final URI uri = builder.build();
948         Assertions.assertEquals("https", builder.getScheme());
949         Assertions.assertEquals("https", uri.getScheme());
950         Assertions.assertEquals(443, builder.getPort());
951         Assertions.assertEquals(443, uri.getPort());
952         Assertions.assertEquals("::1", builder.getHost());
953         Assertions.assertEquals("[::1]", uri.getHost());
954         Assertions.assertEquals("/path", builder.getPath());
955         Assertions.assertEquals("/path", uri.getPath());
956     }
957 }