diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 831223db0..33bcc480d 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,5 +1,8 @@ Changes since 4.1.1 +* [HTTPCLIENT-1092] If ClientPNames.VIRTUAL_HOST does not provide the port, derive it from the current request. + Contributed by Sebastian Bazley + * [HTTPCLIENT-1087] NTLM proxy authentication fails on retry if the underlying connection is closed as a result of a target authentication failure. Contributed by Oleg Kalnichevski diff --git a/httpclient/src/main/java/org/apache/http/client/params/ClientPNames.java b/httpclient/src/main/java/org/apache/http/client/params/ClientPNames.java index 67860dd50..021b838e4 100644 --- a/httpclient/src/main/java/org/apache/http/client/params/ClientPNames.java +++ b/httpclient/src/main/java/org/apache/http/client/params/ClientPNames.java @@ -100,11 +100,12 @@ public interface ClientPNames { public static final String COOKIE_POLICY = "http.protocol.cookie-policy"; /** - * Defines the virtual host name to be used in the Host - * request header instead of the physical host name. + * Defines the virtual host to be used in the Host + * request header instead of the physical host. *

* This parameter expects a value of type {@link org.apache.http.HttpHost}. *

+ * If a port is not provided, it will be derived from the request URL. */ public static final String VIRTUAL_HOST = "http.virtual-host"; diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultRequestDirector.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultRequestDirector.java index 9ba592b33..1615fa57a 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultRequestDirector.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultRequestDirector.java @@ -358,6 +358,14 @@ public class DefaultRequestDirector implements RequestDirector { virtualHost = (HttpHost) orig.getParams().getParameter( ClientPNames.VIRTUAL_HOST); + + // HTTPCLIENT-1092 - add the port if necessary + if (virtualHost != null && virtualHost.getPort() == -1) { + int port = target.getPort(); + if (port != -1){ + virtualHost = new HttpHost(virtualHost.getHostName(), port, virtualHost.getSchemeName()); + } + } RoutedRequest roureq = new RoutedRequest(origWrapper, origRoute); diff --git a/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultClientRequestDirector.java b/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultClientRequestDirector.java index 149a85903..f2ca85780 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultClientRequestDirector.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultClientRequestDirector.java @@ -611,6 +611,90 @@ public class TestDefaultClientRequestDirector extends BasicServerTestBase { Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode()); } + @Test + public void testDefaultHostHeader() throws Exception { + int port = this.localServer.getServiceAddress().getPort(); + this.localServer.register("*", new SimpleService()); + + HttpContext context = new BasicHttpContext(); + + String s = "http://localhost:" + port; + HttpGet httpget = new HttpGet(s); + + DefaultHttpClient client = new DefaultHttpClient(); + HttpResponse response = client.execute(getServerHttp(), httpget, context); + EntityUtils.consume(response.getEntity()); + + HttpRequest reqWrapper = (HttpRequest) context.getAttribute( + ExecutionContext.HTTP_REQUEST); + + Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode()); + // Check that Host header is generated as expected + Header[] headers = reqWrapper.getHeaders("host"); + Assert.assertNotNull(headers); + Assert.assertEquals(1, headers.length); + Assert.assertEquals("localhost:"+port,headers[0].getValue()); + } + + @Test + // HTTPCLIENT-1092 + public void testVirtualHostHeader() throws Exception { + int port = this.localServer.getServiceAddress().getPort(); + this.localServer.register("*", new SimpleService()); + + HttpContext context = new BasicHttpContext(); + + String s = "http://localhost:" + port; + HttpGet httpget = new HttpGet(s); + + DefaultHttpClient client = new DefaultHttpClient(); + String virtHost = "virtual"; + httpget.getParams().setParameter(ClientPNames.VIRTUAL_HOST, new HttpHost(virtHost, port)); + HttpResponse response = client.execute(getServerHttp(), httpget, context); + EntityUtils.consume(response.getEntity()); + + HttpRequest reqWrapper = (HttpRequest) context.getAttribute( + ExecutionContext.HTTP_REQUEST); + + Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode()); + // Check that Host header is generated as expected + Header[] headers = reqWrapper.getHeaders("host"); + Assert.assertNotNull(headers); + Assert.assertEquals(1, headers.length); + Assert.assertEquals(virtHost+":"+port,headers[0].getValue()); + } + + @Test + // Test that virtual port is propagated if provided + // This is not expected to be used much, if ever + // HTTPCLIENT-1092 + public void testVirtualHostPortHeader() throws Exception { + int port = this.localServer.getServiceAddress().getPort(); + this.localServer.register("*", new SimpleService()); + + HttpContext context = new BasicHttpContext(); + + String s = "http://localhost:" + port; + HttpGet httpget = new HttpGet(s); + + DefaultHttpClient client = new DefaultHttpClient(); + String virtHost = "virtual"; + int virtPort = 9876; + httpget.getParams().setParameter(ClientPNames.VIRTUAL_HOST, new HttpHost(virtHost, virtPort)); + HttpResponse response = client.execute(getServerHttp(), httpget, context); + EntityUtils.consume(response.getEntity()); + + HttpRequest reqWrapper = (HttpRequest) context.getAttribute( + ExecutionContext.HTTP_REQUEST); + + Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode()); + // Check that Host header is generated as expected + Header[] headers = reqWrapper.getHeaders("host"); + Assert.assertNotNull(headers); + Assert.assertEquals(1, headers.length); + Assert.assertEquals(virtHost+":"+virtPort,headers[0].getValue()); + } + @Test public void testDefaultHostAtRequestLevel() throws Exception { int port = this.localServer.getServiceAddress().getPort(); diff --git a/src/docbkx/httpagent.xml b/src/docbkx/httpagent.xml index 3ed42ec30..94ab8c5be 100644 --- a/src/docbkx/httpagent.xml +++ b/src/docbkx/httpagent.xml @@ -144,10 +144,12 @@ httpclient.getConnectionManager().shutdown(); <constant>ClientPNames.VIRTUAL_HOST</constant>='http.virtual-host': - defines the virtual host name to be used in the Host - header instead of the physical host name. This parameter expects a value of - type HttpHost. If this parameter is not set, the name or - IP address of the target host will be used. + defines the virtual host settings to be used in the Host + header instead of the physical host. This parameter expects a value of + type HttpHost. The HttpHost port does not have to + be specified as it will be derived from the target. + If this parameter is not set, the name or + IP address (and port if required) of the target host will be used.