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.net.URLEncoder;
32  import java.nio.charset.Charset;
33  import java.nio.charset.StandardCharsets;
34  import java.util.ArrayList;
35  import java.util.Arrays;
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.message.BasicNameValuePair;
41  import org.hamcrest.CoreMatchers;
42  import org.junit.Assert;
43  import org.junit.Test;
44  
45  public class TestURIBuilder {
46  
47      @Test
48      public void testHierarchicalUri() throws Exception {
49          final URI uri = new URI("http", "stuff", "localhost", 80, "/some stuff", "param=stuff", "fragment");
50          final URIBuilder uribuilder = new URIBuilder(uri);
51          final URI result = uribuilder.build();
52          Assert.assertEquals(new URI("http://stuff@localhost:80/some%20stuff?param=stuff#fragment"), result);
53      }
54  
55      @Test
56      public void testMutationToRelativeUri() throws Exception {
57          final URI uri = new URI("http://stuff@localhost:80/stuff?param=stuff#fragment");
58          final URIBuilder uribuilder = new URIBuilder(uri).setHost((String) null);
59          final URI result = uribuilder.build();
60          Assert.assertEquals(new URI("http:///stuff?param=stuff#fragment"), result);
61      }
62  
63      @Test
64      public void testMutationRemoveFragment() throws Exception {
65          final URI uri = new URI("http://stuff@localhost:80/stuff?param=stuff#fragment");
66          final URI result = new URIBuilder(uri).setFragment(null).build();
67          Assert.assertEquals(new URI("http://stuff@localhost:80/stuff?param=stuff"), result);
68      }
69  
70      @Test
71      public void testMutationRemoveUserInfo() throws Exception {
72          final URI uri = new URI("http://stuff@localhost:80/stuff?param=stuff#fragment");
73          final URI result = new URIBuilder(uri).setUserInfo(null).build();
74          Assert.assertEquals(new URI("http://localhost:80/stuff?param=stuff#fragment"), result);
75      }
76  
77      @Test
78      public void testMutationRemovePort() throws Exception {
79          final URI uri = new URI("http://stuff@localhost:80/stuff?param=stuff#fragment");
80          final URI result = new URIBuilder(uri).setPort(-1).build();
81          Assert.assertEquals(new URI("http://stuff@localhost/stuff?param=stuff#fragment"), result);
82      }
83  
84      @Test
85      public void testOpaqueUri() throws Exception {
86          final URI uri = new URI("stuff", "some-stuff", "fragment");
87          final URIBuilder uribuilder = new URIBuilder(uri);
88          final URI result = uribuilder.build();
89          Assert.assertEquals(uri, result);
90      }
91  
92      @Test
93      public void testOpaqueUriMutation() throws Exception {
94          final URI uri = new URI("stuff", "some-stuff", "fragment");
95          final URIBuilder uribuilder = new URIBuilder(uri).setCustomQuery("param1&param2=stuff").setFragment(null);
96          Assert.assertEquals(new URI("stuff:?param1&param2=stuff"), uribuilder.build());
97      }
98  
99      @Test
100     public void testHierarchicalUriMutation() throws Exception {
101         final URIBuilder uribuilder = new URIBuilder("/").setScheme("http").setHost("localhost").setPort(80).setPath("/stuff");
102         Assert.assertEquals(new URI("http://localhost:80/stuff"), uribuilder.build());
103     }
104 
105     @Test
106    public void testLocalhost() throws Exception {
107        // Check that the URI generated by URI builder agrees with that generated by using URI directly
108        final String scheme="https";
109        final InetAddress host=InetAddress.getLocalHost();
110        final String specials="/abcd!$&*()_-+.,=:;'~@[]?<>|#^%\"{}\\\u00a3`\u00ac\u00a6xyz"; // N.B. excludes space
111        final URI uri = new URI(scheme, specials, host.getHostAddress(), 80, specials, specials, specials);
112 
113        final URI bld = URIBuilder.localhost()
114                .setScheme(scheme)
115                .setUserInfo(specials)
116                .setPath(specials)
117                .setCustomQuery(specials)
118                .setFragment(specials)
119                .build();
120 
121        Assert.assertEquals(uri.getHost(), bld.getHost());
122 
123        Assert.assertEquals(uri.getUserInfo(), bld.getUserInfo());
124 
125        Assert.assertEquals(uri.getPath(), bld.getPath());
126 
127        Assert.assertEquals(uri.getQuery(), bld.getQuery());
128 
129        Assert.assertEquals(uri.getFragment(), bld.getFragment());
130    }
131 
132     @Test
133    public void testLoopbackAddress() throws Exception {
134        // Check that the URI generated by URI builder agrees with that generated by using URI directly
135        final String scheme="https";
136        final InetAddress host=InetAddress.getLoopbackAddress();
137        final String specials="/abcd!$&*()_-+.,=:;'~@[]?<>|#^%\"{}\\\u00a3`\u00ac\u00a6xyz"; // N.B. excludes space
138        final URI uri = new URI(scheme, specials, host.getHostAddress(), 80, specials, specials, specials);
139 
140        final URI bld = URIBuilder.loopbackAddress()
141                .setScheme(scheme)
142                .setUserInfo(specials)
143                .setPath(specials)
144                .setCustomQuery(specials)
145                .setFragment(specials)
146                .build();
147 
148        Assert.assertEquals(uri.getHost(), bld.getHost());
149 
150        Assert.assertEquals(uri.getUserInfo(), bld.getUserInfo());
151 
152        Assert.assertEquals(uri.getPath(), bld.getPath());
153 
154        Assert.assertEquals(uri.getQuery(), bld.getQuery());
155 
156        Assert.assertEquals(uri.getFragment(), bld.getFragment());
157    }
158 
159     @Test
160     public void testEmpty() throws Exception {
161         final URIBuilder uribuilder = new URIBuilder();
162         final URI result = uribuilder.build();
163         Assert.assertEquals(new URI(""), result);
164     }
165 
166     @Test
167     public void testEmptyPath() throws Exception {
168         final URIBuilder uribuilder = new URIBuilder("http://thathost");
169         Assert.assertTrue(uribuilder.isPathEmpty());
170     }
171 
172     @Test
173     public void testSetUserInfo() throws Exception {
174         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff", null);
175         final URIBuilder uribuilder = new URIBuilder(uri).setUserInfo("user", "password");
176         final URI result = uribuilder.build();
177         Assert.assertEquals(new URI("http://user:password@localhost:80/?param=stuff"), result);
178     }
179 
180     @Test
181     public void testRemoveParameters() throws Exception {
182         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff", null);
183         final URIBuilder uribuilder = new URIBuilder(uri).removeQuery();
184         final URI result = uribuilder.build();
185         Assert.assertEquals(new URI("http://localhost:80/"), result);
186     }
187 
188     @Test
189     public void testSetParameter() throws Exception {
190         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff&blah&blah", null);
191         final URIBuilder uribuilder = new URIBuilder(uri).setParameter("param", "some other stuff")
192             .setParameter("blah", "blah");
193         final URI result = uribuilder.build();
194         Assert.assertEquals(new URI("http://localhost:80/?param=some+other+stuff&blah=blah"), result);
195     }
196 
197     @Test
198     public void testSetParametersWithEmptyArg() throws Exception {
199         final URI uri = new URI("http", null, "localhost", 80, "/test", "param=test", null);
200         final URIBuilder uribuilder = new URIBuilder(uri).setParameters();
201         final URI result = uribuilder.build();
202         Assert.assertEquals(new URI("http://localhost:80/test"), result);
203     }
204 
205     @Test
206     public void testSetParametersWithEmptyList() throws Exception {
207         final URI uri = new URI("http", null, "localhost", 80, "/test", "param=test", null);
208         final URIBuilder uribuilder = new URIBuilder(uri).setParameters(Arrays.<NameValuePair>asList());
209         final URI result = uribuilder.build();
210         Assert.assertEquals(new URI("http://localhost:80/test"), result);
211     }
212 
213     @Test
214     public void testParameterWithSpecialChar() throws Exception {
215         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff", null);
216         final URIBuilder uribuilder = new URIBuilder(uri).addParameter("param", "1 + 1 = 2")
217             .addParameter("param", "blah&blah");
218         final URI result = uribuilder.build();
219         Assert.assertEquals(new URI("http://localhost:80/?param=stuff&param=1+%2B+1+%3D+2&" +
220                 "param=blah%26blah"), result);
221     }
222 
223     @Test
224     public void testAddParameter() throws Exception {
225         final URI uri = new URI("http", null, "localhost", 80, "/", "param=stuff&blah&blah", null);
226         final URIBuilder uribuilder = new URIBuilder(uri).addParameter("param", "some other stuff")
227             .addParameter("blah", "blah");
228         final URI result = uribuilder.build();
229         Assert.assertEquals(new URI("http://localhost:80/?param=stuff&blah&blah&" +
230                 "param=some+other+stuff&blah=blah"), result);
231     }
232 
233     @Test
234     public void testQueryEncoding() throws Exception {
235         final URI uri1 = new URI("https://somehost.com/stuff?client_id=1234567890" +
236                 "&redirect_uri=https%3A%2F%2Fsomehost.com%2Fblah+blah%2F");
237         final URI uri2 = new URIBuilder("https://somehost.com/stuff")
238             .addParameter("client_id","1234567890")
239             .addParameter("redirect_uri","https://somehost.com/blah blah/").build();
240         Assert.assertEquals(uri1, uri2);
241     }
242 
243     @Test
244     public void testQueryAndParameterEncoding() throws Exception {
245         final URI uri1 = new URI("https://somehost.com/stuff?param1=12345&param2=67890");
246         final URI uri2 = new URIBuilder("https://somehost.com/stuff")
247             .setCustomQuery("this&that")
248             .addParameter("param1","12345")
249             .addParameter("param2","67890").build();
250         Assert.assertEquals(uri1, uri2);
251     }
252 
253     @Test
254     public void testPathEncoding() throws Exception {
255         final URI uri1 = new URI("https://somehost.com/some%20path%20with%20blanks/");
256         final URI uri2 = new URIBuilder()
257             .setScheme("https")
258             .setHost("somehost.com")
259             .setPath("/some path with blanks/")
260             .build();
261         Assert.assertEquals(uri1, uri2);
262     }
263 
264     @Test
265     public void testAgainstURI() throws Exception {
266         // Check that the URI generated by URI builder agrees with that generated by using URI directly
267         final String scheme="https";
268         final String host="localhost";
269         final String specials="/abcd!$&*()_-+.,=:;'~@[]?<>|#^%\"{}\\\u00a3`\u00ac\u00a6xyz"; // N.B. excludes space
270         final URI uri = new URI(scheme, specials, host, 80, specials, specials, specials);
271 
272         final URI bld = new URIBuilder()
273                 .setScheme(scheme)
274                 .setHost(host)
275                 .setUserInfo(specials)
276                 .setPath(specials)
277                 .setCustomQuery(specials)
278                 .setFragment(specials)
279                 .build();
280 
281         Assert.assertEquals(uri.getHost(), bld.getHost());
282 
283         Assert.assertEquals(uri.getUserInfo(), bld.getUserInfo());
284 
285         Assert.assertEquals(uri.getPath(), bld.getPath());
286 
287         Assert.assertEquals(uri.getQuery(), bld.getQuery());
288 
289         Assert.assertEquals(uri.getFragment(), bld.getFragment());
290 
291     }
292 
293     @Test
294     public void testAgainstURIEncoded() throws Exception {
295         // Check that the encoded URI generated by URI builder agrees with that generated by using URI directly
296         final String scheme="https";
297         final String host="localhost";
298         final String specials="/ abcd!$&*()_-+.,=:;'~<>/@[]|#^%\"{}\\`xyz"; // N.B. excludes \u00a3\u00ac\u00a6
299         final URI uri = new URI(scheme, specials, host, 80, specials, specials, specials);
300 
301         final URI bld = new URIBuilder()
302                 .setScheme(scheme)
303                 .setHost(host)
304                 .setUserInfo(specials)
305                 .setPath(specials)
306                 .setCustomQuery(specials)
307                 .setFragment(specials)
308                 .build();
309 
310         Assert.assertEquals(uri.getHost(), bld.getHost());
311 
312         Assert.assertEquals(uri.getRawUserInfo(), bld.getRawUserInfo());
313 
314         Assert.assertEquals(uri.getRawPath(), bld.getRawPath());
315 
316         Assert.assertEquals(uri.getRawQuery(), bld.getRawQuery());
317 
318         Assert.assertEquals(uri.getRawFragment(), bld.getRawFragment());
319 
320     }
321 
322     @Test
323     public void testBuildAddParametersUTF8() throws Exception {
324         assertAddParameters(StandardCharsets.UTF_8);
325     }
326 
327     @Test
328     public void testBuildAddParametersISO88591() throws Exception {
329         assertAddParameters(StandardCharsets.ISO_8859_1);
330     }
331 
332     public void assertAddParameters(final Charset charset) throws Exception {
333         final URI uri = new URIBuilder("https://somehost.com/stuff")
334                 .setCharset(charset)
335                 .addParameters(createParameters()).build();
336 
337         assertBuild(charset, uri);
338     }
339 
340     @Test
341     public void testBuildSetParametersUTF8() throws Exception {
342         assertSetParameters(StandardCharsets.UTF_8);
343     }
344 
345     @Test
346     public void testBuildSetParametersISO88591() throws Exception {
347         assertSetParameters(StandardCharsets.ISO_8859_1);
348     }
349 
350     public void assertSetParameters(final Charset charset) throws Exception {
351         final URI uri = new URIBuilder("https://somehost.com/stuff")
352                 .setCharset(charset)
353                 .setParameters(createParameters()).build();
354 
355         assertBuild(charset, uri);
356     }
357 
358     public void assertBuild(final Charset charset, final URI uri) throws Exception {
359         final String encodedData1 = URLEncoder.encode("\"1\u00aa position\"", charset.displayName());
360         final String encodedData2 = URLEncoder.encode("Jos\u00e9 Abra\u00e3o", charset.displayName());
361 
362         final String uriExpected = String.format("https://somehost.com/stuff?parameter1=value1&parameter2=%s&parameter3=%s", encodedData1, encodedData2);
363 
364         Assert.assertEquals(uriExpected, uri.toString());
365     }
366 
367     private List<NameValuePair> createParameters() {
368         final List<NameValuePair> parameters = new ArrayList<>();
369         parameters.add(new BasicNameValuePair("parameter1", "value1"));
370         parameters.add(new BasicNameValuePair("parameter2", "\"1\u00aa position\""));
371         parameters.add(new BasicNameValuePair("parameter3", "Jos\u00e9 Abra\u00e3o"));
372         return parameters;
373     }
374 
375     @Test
376     public void testMalformedPath() throws Exception {
377         final String path = "@notexample.com/mypath";
378         final URI uri = new URIBuilder(path).setHost("example.com").build();
379         Assert.assertEquals("example.com", uri.getHost());
380     }
381 
382     @Test
383     public void testRelativePath() throws Exception {
384         final URI uri = new URIBuilder("./mypath").build();
385         Assert.assertEquals(new URI("./mypath"), uri);
386     }
387 
388     @Test
389     public void testRelativePathWithAuthority() throws Exception {
390         final URI uri = new URIBuilder("./mypath").setHost("somehost").setScheme("http").build();
391         Assert.assertEquals(new URI("http://somehost/./mypath"), uri);
392     }
393 
394     @Test
395     public void testTolerateNullInput() throws Exception {
396         Assert.assertThat(new URIBuilder()
397                         .setScheme(null)
398                         .setHost("localhost")
399                         .setUserInfo(null)
400                         .setPort(8443)
401                         .setPath(null)
402                         .setCustomQuery(null)
403                         .setFragment(null)
404                         .build(),
405                 CoreMatchers.equalTo(URI.create("//localhost:8443")));
406     }
407 
408     @Test
409     public void testTolerateBlankInput() throws Exception {
410         Assert.assertThat(new URIBuilder()
411                         .setScheme("")
412                         .setHost("localhost")
413                         .setUserInfo("")
414                         .setPort(8443)
415                         .setPath("")
416                         .setPath("")
417                         .setCustomQuery("")
418                         .setFragment("")
419                         .build(),
420                 CoreMatchers.equalTo(URI.create("//localhost:8443")));
421     }
422 
423     @Test
424     public void testHttpHost() throws Exception {
425         final HttpHost httpHost = new HttpHost("http", "example.com", 1234);
426         final URIBuilder uribuilder = new URIBuilder();
427         uribuilder.setHttpHost(httpHost);
428         final URI result = uribuilder.build();
429         Assert.assertEquals(URI.create(httpHost.toURI()), result);
430     }
431 
432     @Test
433     public void testMultipleLeadingPathSlashes() throws Exception {
434         final URI uri = new URIBuilder()
435                 .setScheme("ftp")
436                 .setHost("somehost")
437                 .setPath("//blah//blah")
438                 .build();
439         Assert.assertThat(uri, CoreMatchers.equalTo(URI.create("ftp://somehost//blah//blah")));
440     }
441 
442     @Test
443     public void testPathNoLeadingSlash() throws Exception {
444         final URI uri = new URIBuilder()
445                 .setScheme("ftp")
446                 .setPath("blah")
447                 .build();
448         Assert.assertThat(uri, CoreMatchers.equalTo(URI.create("ftp:/blah")));
449     }
450 
451     @Test
452     public void testOpaque() throws Exception {
453         final URIBuilder uriBuilder = new URIBuilder("http://host.com");
454         final URI uri = uriBuilder.build();
455         Assert.assertThat(uriBuilder.isOpaque(), CoreMatchers.equalTo(uri.isOpaque()));
456     }
457 
458 }