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