diff --git a/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java b/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java index 4744a789c..3e69610cf 100644 --- a/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java +++ b/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java @@ -277,6 +277,56 @@ public class URIUtils { } } + /** + * Extracts target host from the given {@link URI}. + * + * @param uri + * @return the target host if the URI is absolute or null if the URI is + * relative or does not contain a valid host name. + * + * @since 4.1 + */ + public static HttpHost exctractHost(final URI uri) { + if (uri == null) { + return null; + } + HttpHost target = null; + if (uri.isAbsolute()) { + int port = uri.getPort(); // may be overridden later + String host = uri.getHost(); + if (host == null) { // normal parse failed; let's do it ourselves + // authority does not seem to care about the valid character-set for host names + host = uri.getAuthority(); + if (host != null) { + // Strip off any leading user credentials + int at = host.indexOf('@'); + if (at >= 0) { + if (host.length() > at+1 ) { + host = host.substring(at+1); + } else { + host = null; // @ on its own + } + } + // Extract the port suffix, if present + if (host != null) { + int colon = host.indexOf(':'); + if (colon >= 0) { + if (colon+1 < host.length()) { + port = Integer.parseInt(host.substring(colon+1)); + } + host = host.substring(0,colon); + } + } + } + } + String scheme = uri.getScheme(); + if (host != null) { + target = new HttpHost(host, port, scheme); + } + } + return target; + } + /** * This class should not be instantiated. */ diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AbstractHttpClient.java b/httpclient/src/main/java/org/apache/http/impl/client/AbstractHttpClient.java index 6a30f93bd..d7a634522 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/AbstractHttpClient.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/AbstractHttpClient.java @@ -57,6 +57,7 @@ import org.apache.http.client.HttpClient; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.UserTokenHandler; import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.utils.URIUtils; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.conn.routing.HttpRoutePlanner; @@ -626,47 +627,18 @@ public abstract class AbstractHttpClient implements HttpClient { return execute(determineTarget(request), request, context); } - // Package-protected so can be accessed from unit tests - static HttpHost determineTarget(HttpUriRequest request) throws ClientProtocolException { + private static HttpHost determineTarget(HttpUriRequest request) throws ClientProtocolException { // A null target may be acceptable if there is a default target. // Otherwise, the null target is detected in the director. HttpHost target = null; URI requestURI = request.getURI(); if (requestURI.isAbsolute()) { - int port = requestURI.getPort(); // may be overridden later - String host = requestURI.getHost(); - if (host == null) { // normal parse failed; let's do it ourselves - // authority does not seem to care about the valid character-set for host names - host = requestURI.getAuthority(); - if (host != null) { - // Strip off any leading user credentials - int at = host.indexOf('@'); - if (at >= 0) { - if (host.length() > at+1 ) { - host = host.substring(at+1); - } else { - host = null; // @ on its own - } - } - // Extract the port suffix, if present - if (host != null) { - int colon = host.indexOf(':'); - if (colon >= 0) { - if (colon+1 < host.length()) { - port = Integer.parseInt(host.substring(colon+1)); - } - host = host.substring(0,colon); - } - } - } - } - String scheme = requestURI.getScheme(); - if (host == null) { + target = URIUtils.exctractHost(requestURI); + if (target == null) { throw new ClientProtocolException( "URI does not specify a valid host name: " + requestURI); } - target = new HttpHost(host, port, scheme); } return target; } diff --git a/httpclient/src/test/java/org/apache/http/client/utils/TestURIUtils.java b/httpclient/src/test/java/org/apache/http/client/utils/TestURIUtils.java index e22aa7ac1..abc8d7822 100644 --- a/httpclient/src/test/java/org/apache/http/client/utils/TestURIUtils.java +++ b/httpclient/src/test/java/org/apache/http/client/utils/TestURIUtils.java @@ -317,4 +317,27 @@ public class TestURIUtils { "http://s/mid/content=5/../6").toString()); } + @Test + public void testHTTPCLIENT_911() throws Exception{ + Assert.assertEquals(new HttpHost("localhost"),URIUtils.exctractHost(new URI("http://localhost/abcd"))); + Assert.assertEquals(new HttpHost("localhost"),URIUtils.exctractHost(new URI("http://localhost/abcd%3A"))); + + Assert.assertEquals(new HttpHost("local_host"),URIUtils.exctractHost(new URI("http://local_host/abcd"))); + Assert.assertEquals(new HttpHost("local_host"),URIUtils.exctractHost(new URI("http://local_host/abcd%3A"))); + + Assert.assertEquals(new HttpHost("localhost",8),URIUtils.exctractHost(new URI("http://localhost:8/abcd"))); + Assert.assertEquals(new HttpHost("local_host",8),URIUtils.exctractHost(new URI("http://local_host:8/abcd"))); + + // URI seems to OK with missing port number + Assert.assertEquals(new HttpHost("localhost"),URIUtils.exctractHost(new URI("http://localhost:/abcd"))); + Assert.assertEquals(new HttpHost("local_host"),URIUtils.exctractHost(new URI("http://local_host:/abcd"))); + + Assert.assertEquals(new HttpHost("localhost",8080),URIUtils.exctractHost(new URI("http://user:pass@localhost:8080/abcd"))); + Assert.assertEquals(new HttpHost("local_host",8080),URIUtils.exctractHost(new URI("http://user:pass@local_host:8080/abcd"))); + + Assert.assertEquals(new HttpHost("localhost",8080),URIUtils.exctractHost(new URI("http://@localhost:8080/abcd"))); + Assert.assertEquals(new HttpHost("local_host",8080),URIUtils.exctractHost(new URI("http://@local_host:8080/abcd"))); + + } + } diff --git a/httpclient/src/test/java/org/apache/http/impl/client/TestAbstractHttpClient.java b/httpclient/src/test/java/org/apache/http/impl/client/TestAbstractHttpClient.java deleted file mode 100644 index b70b145d4..000000000 --- a/httpclient/src/test/java/org/apache/http/impl/client/TestAbstractHttpClient.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.http.impl.client; - -import static org.junit.Assert.assertEquals; - -import org.apache.http.HttpHost; -import org.apache.http.client.methods.HttpHead; -import org.junit.Test; - -/** - * Unit tests for {@link AbstractHttpClient}. - */ -public class TestAbstractHttpClient { - - @Test - public void testHTTPCLIENT_911() throws Exception{ - assertEquals(new HttpHost("localhost"),AbstractHttpClient.determineTarget(new HttpHead("http://localhost/abcd"))); - assertEquals(new HttpHost("localhost"),AbstractHttpClient.determineTarget(new HttpHead("http://localhost/abcd%3A"))); - - assertEquals(new HttpHost("local_host"),AbstractHttpClient.determineTarget(new HttpHead("http://local_host/abcd"))); - assertEquals(new HttpHost("local_host"),AbstractHttpClient.determineTarget(new HttpHead("http://local_host/abcd%3A"))); - - assertEquals(new HttpHost("localhost",8),AbstractHttpClient.determineTarget(new HttpHead("http://localhost:8/abcd"))); - assertEquals(new HttpHost("local_host",8),AbstractHttpClient.determineTarget(new HttpHead("http://local_host:8/abcd"))); - - // URI seems to OK with missing port number - assertEquals(new HttpHost("localhost"),AbstractHttpClient.determineTarget(new HttpHead("http://localhost:/abcd"))); - assertEquals(new HttpHost("local_host"),AbstractHttpClient.determineTarget(new HttpHead("http://local_host:/abcd"))); - - assertEquals(new HttpHost("localhost",8080),AbstractHttpClient.determineTarget(new HttpHead("http://user:pass@localhost:8080/abcd"))); - assertEquals(new HttpHost("local_host",8080),AbstractHttpClient.determineTarget(new HttpHead("http://user:pass@local_host:8080/abcd"))); - - assertEquals(new HttpHost("localhost",8080),AbstractHttpClient.determineTarget(new HttpHead("http://@localhost:8080/abcd"))); - assertEquals(new HttpHost("local_host",8080),AbstractHttpClient.determineTarget(new HttpHead("http://@local_host:8080/abcd"))); - - } -}