diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 44b9022d0..557a635e8 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,5 +1,9 @@ Changes since release 4.0 Alpha 1 +* [HTTPCLIENT-698] Resolve non-absolute redirect URIs relative to + the request URI + Contributed by Johannes Koch + * [HTTPCLIENT-697] Throw a more intelligible exception when connection to a remote host cannot be established. Contributed by Oleg Kalnichevski diff --git a/module-client/src/main/java/org/apache/http/impl/client/DefaultRedirectHandler.java b/module-client/src/main/java/org/apache/http/impl/client/DefaultRedirectHandler.java index 6bef28a15..a7f51d1ae 100644 --- a/module-client/src/main/java/org/apache/http/impl/client/DefaultRedirectHandler.java +++ b/module-client/src/main/java/org/apache/http/impl/client/DefaultRedirectHandler.java @@ -40,6 +40,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.Header; import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.ProtocolException; @@ -131,15 +132,21 @@ public class DefaultRedirectHandler implements RedirectHandler { throw new IllegalStateException("Target host not available " + "in the HTTP context"); } + + HttpRequest request = (HttpRequest) context.getAttribute( + ExecutionContext.HTTP_REQUEST); + try { - uri = new URI( + URI requestURI = new URI(request.getRequestLine().getUri()); + URI absoluteRequestURI = new URI( target.getSchemeName(), null, target.getHostName(), target.getPort(), - uri.getPath(), - uri.getQuery(), - uri.getFragment()); + requestURI.getPath(), + requestURI.getQuery(), + requestURI.getFragment()); + uri = absoluteRequestURI.resolve(uri); } catch (URISyntaxException ex) { throw new ProtocolException(ex.getMessage(), ex); } diff --git a/module-client/src/test/java/org/apache/http/client/protocol/TestRedirects.java b/module-client/src/test/java/org/apache/http/client/protocol/TestRedirects.java index cf45fbd71..ad946fa90 100644 --- a/module-client/src/test/java/org/apache/http/client/protocol/TestRedirects.java +++ b/module-client/src/test/java/org/apache/http/client/protocol/TestRedirects.java @@ -158,28 +158,53 @@ public class TestRedirects extends ServerTestBase { private class RelativeRedirectService implements HttpRequestHandler { - public RelativeRedirectService() { - super(); - } + public RelativeRedirectService() { + super(); + } - public void handle( - final HttpRequest request, - final HttpResponse response, - final HttpContext context) throws HttpException, IOException { - ProtocolVersion ver = request.getRequestLine().getProtocolVersion(); - String uri = request.getRequestLine().getUri(); - if (uri.equals("/oldlocation/")) { - response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY); - response.addHeader(new BasicHeader("Location", "/relativelocation/")); - } else if (uri.equals("/relativelocation/")) { - response.setStatusLine(ver, HttpStatus.SC_OK); - StringEntity entity = new StringEntity("Successful redirect"); - response.setEntity(entity); - } else { - response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND); - } + public void handle( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws HttpException, IOException { + ProtocolVersion ver = request.getRequestLine().getProtocolVersion(); + String uri = request.getRequestLine().getUri(); + if (uri.equals("/oldlocation/")) { + response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY); + response.addHeader(new BasicHeader("Location", "/relativelocation/")); + } else if (uri.equals("/relativelocation/")) { + response.setStatusLine(ver, HttpStatus.SC_OK); + StringEntity entity = new StringEntity("Successful redirect"); + response.setEntity(entity); + } else { + response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND); } } + } + + private class RelativeRedirectService2 implements HttpRequestHandler { + + public RelativeRedirectService2() { + super(); + } + + public void handle( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws HttpException, IOException { + ProtocolVersion ver = request.getRequestLine().getProtocolVersion(); + String uri = request.getRequestLine().getUri(); + if (uri.equals("/test/oldlocation")) { + response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY); + response.addHeader(new BasicHeader("Location", "relativelocation")); + } else if (uri.equals("/test/relativelocation")) { + response.setStatusLine(ver, HttpStatus.SC_OK); + StringEntity entity = new StringEntity("Successful redirect"); + response.setEntity(entity); + } else { + response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND); + } + } + } private class BogusRedirectService implements HttpRequestHandler { private String url; @@ -490,6 +515,36 @@ public class TestRedirects extends ServerTestBase { assertEquals(port, targetHost.getPort()); } + public void testRelativeRedirect2() throws Exception { + int port = this.localServer.getServicePort(); + String host = "localhost"; + this.localServer.register("*", new RelativeRedirectService2()); + + DefaultHttpClient client = new DefaultHttpClient(); + HttpContext context = client.getDefaultContext(); + + client.getParams().setBooleanParameter( + ClientPNames.REJECT_RELATIVE_REDIRECT, false); + HttpGet httpget = new HttpGet("/test/oldlocation"); + + RoutedRequest request = new RoutedRequest.Impl(httpget, getDefaultRoute()); + HttpResponse response = client.execute(request, context); + HttpEntity e = response.getEntity(); + if (e != null) { + e.consumeContent(); + } + + HttpRequest reqWrapper = (HttpRequest) context.getAttribute( + ExecutionContext.HTTP_REQUEST); + HttpHost targetHost = (HttpHost) context.getAttribute( + ExecutionContext.HTTP_TARGET_HOST); + + assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode()); + assertEquals("/test/relativelocation", reqWrapper.getRequestLine().getUri()); + assertEquals(host, targetHost.getHostName()); + assertEquals(port, targetHost.getPort()); + } + public void testRejectRelativeRedirect() throws Exception { this.localServer.register("*", new RelativeRedirectService());