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