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