1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.client5.http.utils;
28
29 import java.net.URI;
30 import java.net.URISyntaxException;
31 import java.util.ArrayList;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Locale;
35 import java.util.Stack;
36
37 import org.apache.hc.core5.http.HttpHost;
38 import org.apache.hc.core5.net.URIAuthority;
39 import org.apache.hc.core5.net.URIBuilder;
40 import org.apache.hc.core5.util.Args;
41 import org.apache.hc.core5.util.TextUtils;
42
43
44
45
46
47
48
49 public class URIUtils {
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public static URI rewriteURI(
68 final URI uri,
69 final HttpHost target,
70 final boolean dropFragment) throws URISyntaxException {
71 Args.notNull(uri, "URI");
72 if (uri.isOpaque()) {
73 return uri;
74 }
75 final URIBuilder uribuilder = new URIBuilder(uri);
76 if (target != null) {
77 uribuilder.setScheme(target.getSchemeName());
78 uribuilder.setHost(target.getHostName());
79 uribuilder.setPort(target.getPort());
80 } else {
81 uribuilder.setScheme(null);
82 uribuilder.setHost((String) null);
83 uribuilder.setPort(-1);
84 }
85 if (dropFragment) {
86 uribuilder.setFragment(null);
87 }
88 final List<String> originalPathSegments = uribuilder.getPathSegments();
89 final List<String> pathSegments = new ArrayList<>(originalPathSegments);
90 for (final Iterator<String> it = pathSegments.iterator(); it.hasNext(); ) {
91 final String pathSegment = it.next();
92 if (pathSegment.isEmpty() && it.hasNext()) {
93 it.remove();
94 }
95 }
96 if (pathSegments.size() != originalPathSegments.size()) {
97 uribuilder.setPathSegments(pathSegments);
98 }
99 if (pathSegments.isEmpty()) {
100 uribuilder.setPathSegments("");
101 }
102 return uribuilder.build();
103 }
104
105
106
107
108
109
110 public static URI rewriteURI(
111 final URI uri,
112 final HttpHost target) throws URISyntaxException {
113 return rewriteURI(uri, target, false);
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127 public static URI rewriteURI(final URI uri) throws URISyntaxException {
128 Args.notNull(uri, "URI");
129 if (uri.isOpaque()) {
130 return uri;
131 }
132 final URIBuilder uribuilder = new URIBuilder(uri);
133 if (uribuilder.getUserInfo() != null) {
134 uribuilder.setUserInfo(null);
135 }
136 if (TextUtils.isEmpty(uribuilder.getPath())) {
137 uribuilder.setPath("/");
138 }
139 if (uribuilder.getHost() != null) {
140 uribuilder.setHost(uribuilder.getHost().toLowerCase(Locale.ROOT));
141 }
142 uribuilder.setFragment(null);
143 return uribuilder.build();
144 }
145
146
147
148
149
150
151
152
153
154 public static URI resolve(final URI baseURI, final String reference) {
155 return resolve(baseURI, URI.create(reference));
156 }
157
158
159
160
161
162
163
164
165
166 public static URI resolve(final URI baseURI, final URI reference) {
167 Args.notNull(baseURI, "Base URI");
168 Args.notNull(reference, "Reference URI");
169 final String s = reference.toASCIIString();
170 if (s.startsWith("?")) {
171 String baseUri = baseURI.toASCIIString();
172 final int i = baseUri.indexOf('?');
173 baseUri = i > -1 ? baseUri.substring(0, i) : baseUri;
174 return URI.create(baseUri + s);
175 }
176 final boolean emptyReference = s.isEmpty();
177 URI resolved;
178 if (emptyReference) {
179 resolved = baseURI.resolve(URI.create("#"));
180 final String resolvedString = resolved.toASCIIString();
181 resolved = URI.create(resolvedString.substring(0, resolvedString.indexOf('#')));
182 } else {
183 resolved = baseURI.resolve(reference);
184 }
185 try {
186 return normalizeSyntax(resolved);
187 } catch (final URISyntaxException ex) {
188 throw new IllegalArgumentException(ex);
189 }
190 }
191
192
193
194
195
196
197
198
199 static URI normalizeSyntax(final URI uri) throws URISyntaxException {
200 if (uri.isOpaque() || uri.getAuthority() == null) {
201
202 return uri;
203 }
204 Args.check(uri.isAbsolute(), "Base URI must be absolute");
205 final URIBuilder builder = new URIBuilder(uri);
206 final String path = builder.getPath();
207 if (path != null && !path.equals("/")) {
208 final String[] inputSegments = path.split("/");
209 final Stack<String> outputSegments = new Stack<>();
210 for (final String inputSegment : inputSegments) {
211 if ((inputSegment.isEmpty()) || (".".equals(inputSegment))) {
212
213 } else if ("..".equals(inputSegment)) {
214 if (!outputSegments.isEmpty()) {
215 outputSegments.pop();
216 }
217 } else {
218 outputSegments.push(inputSegment);
219 }
220 }
221 final StringBuilder outputBuffer = new StringBuilder();
222 for (final String outputSegment : outputSegments) {
223 outputBuffer.append('/').append(outputSegment);
224 }
225 if (path.lastIndexOf('/') == path.length() - 1) {
226
227 outputBuffer.append('/');
228 }
229 builder.setPath(outputBuffer.toString());
230 }
231 if (builder.getScheme() != null) {
232 builder.setScheme(builder.getScheme().toLowerCase(Locale.ROOT));
233 }
234 if (builder.getHost() != null) {
235 builder.setHost(builder.getHost().toLowerCase(Locale.ROOT));
236 }
237 return builder.build();
238 }
239
240
241
242
243
244
245
246
247
248
249 public static HttpHost extractHost(final URI uri) {
250 if (uri == null) {
251 return null;
252 }
253 if (uri.isAbsolute()) {
254 if (uri.getHost() == null) {
255
256 if (uri.getAuthority() != null) {
257 String content = uri.getAuthority();
258
259 int at = content.indexOf('@');
260 if (at != -1) {
261 content = content.substring(at + 1);
262 }
263 final String scheme = uri.getScheme();
264 final String hostname;
265 final int port;
266 at = content.indexOf(":");
267 if (at != -1) {
268 hostname = content.substring(0, at);
269 try {
270 final String portText = content.substring(at + 1);
271 port = !TextUtils.isEmpty(portText) ? Integer.parseInt(portText) : -1;
272 } catch (final NumberFormatException ex) {
273 return null;
274 }
275 } else {
276 hostname = content;
277 port = -1;
278 }
279 try {
280 return new HttpHost(scheme, hostname, port);
281 } catch (final IllegalArgumentException ex) {
282 return null;
283 }
284 }
285 } else {
286 return new HttpHost(uri.getScheme(), uri.getHost(), uri.getPort());
287 }
288 }
289 return null;
290 }
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308 public static URI resolve(
309 final URI originalURI,
310 final HttpHost target,
311 final List<URI> redirects) throws URISyntaxException {
312 Args.notNull(originalURI, "Request URI");
313 final URIBuilder uribuilder;
314 if (redirects == null || redirects.isEmpty()) {
315 uribuilder = new URIBuilder(originalURI);
316 } else {
317 uribuilder = new URIBuilder(redirects.get(redirects.size() - 1));
318 String frag = uribuilder.getFragment();
319
320 for (int i = redirects.size() - 1; frag == null && i >= 0; i--) {
321 frag = redirects.get(i).getFragment();
322 }
323 uribuilder.setFragment(frag);
324 }
325
326 if (uribuilder.getFragment() == null) {
327 uribuilder.setFragment(originalURI.getFragment());
328 }
329
330 if (target != null && !uribuilder.isAbsolute()) {
331 uribuilder.setScheme(target.getSchemeName());
332 uribuilder.setHost(target.getHostName());
333 uribuilder.setPort(target.getPort());
334 }
335 return uribuilder.build();
336 }
337
338
339
340
341
342
343 public static URI create(final HttpHost host, final String path) throws URISyntaxException {
344 final URIBuilder builder = new URIBuilder(path);
345 if (host != null) {
346 builder.setHost(host.getHostName()).setPort(host.getPort()).setScheme(host.getSchemeName());
347 }
348 return builder.build();
349 }
350
351
352
353
354
355
356 public static URI create(final String scheme, final URIAuthority host, final String path) throws URISyntaxException {
357 final URIBuilder builder = new URIBuilder(path);
358 if (scheme != null) {
359 builder.setScheme(scheme);
360 }
361 if (host != null) {
362 builder.setHost(host.getHostName()).setPort(host.getPort());
363 }
364 return builder.build();
365 }
366
367
368
369
370 private URIUtils() {
371 }
372
373 }