Author: olegk
Date: Wed May 29 09:04:54 2013
New Revision: 1487413
URL: http://svn.apache.org/r1487413
Log:
HTTPCLIENT-1351: Added utility method to resolve final location from original request, target
host and a list of redirects
Contributed by James Leigh <james at 3roundstones.com>
Modified:
httpcomponents/httpclient/trunk/RELEASE_NOTES.txt
httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java
(contents, props changed)
httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/client/utils/TestURIUtils.java
(contents, props changed)
httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/integration/TestClientRequestExecution.java
(contents, props changed)
httpcomponents/httpclient/trunk/src/docbkx/httpagent.xml (contents, props changed)
Modified: httpcomponents/httpclient/trunk/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/RELEASE_NOTES.txt?rev=1487413&r1=1487412&r2=1487413&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/RELEASE_NOTES.txt (original)
+++ httpcomponents/httpclient/trunk/RELEASE_NOTES.txt Wed May 29 09:04:54 2013
@@ -4,7 +4,8 @@ Changes since release 4.3 BETA1
* [HTTPCLIENT-1354] do not quote algorithm parameter in DIGEST auth response.
Contributed by Oleg Kalnichevski <olegk at apache.org>
-* [HTTPCLIENT-1351] Preserve last request URI in the execution context.
+* [HTTPCLIENT-1351] Added utility method to resolve final location from original request,
+ target host and a list of redirects.
Contributed by James Leigh <james at 3roundstones.com>
* [HTTPCLIENT-1344] Userinfo credentials in URI should not default to preemptive BASIC
Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java?rev=1487413&r1=1487412&r2=1487413&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java
(original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java
Wed May 29 09:04:54 2013
@@ -28,11 +28,13 @@ package org.apache.http.client.utils;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.List;
import java.util.Locale;
import java.util.Stack;
import org.apache.http.HttpHost;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.URICollection;
import org.apache.http.util.Args;
import org.apache.http.util.TextUtils;
@@ -350,6 +352,52 @@ public class URIUtils {
}
/**
+ * Derives the interpreted (absolute) URI that was used to generate the last
+ * request. This is done by extracting the request-uri and target origin for
+ * the last request and scanning all the redirect locations for the last
+ * fragment identifier, then combining the result into a {@link URI}.
+ *
+ * @param originalURI
+ * original request before any redirects
+ * @param target
+ * if the last URI is relative, it is resolved against this target,
+ * or <code>null</code> if not available.
+ * @param redirects
+ * collection of redirect locations since the original request
+ * or <code>null</code> if not available.
+ * @return interpreted (absolute) URI
+ */
+ public static URI resolve(
+ final URI originalURI,
+ final HttpHost target,
+ final List<URI> redirects) throws URISyntaxException {
+ Args.notNull(originalURI, "Request URI");
+ final URIBuilder uribuilder;
+ if (redirects == null || redirects.isEmpty()) {
+ uribuilder = new URIBuilder(originalURI);
+ } else {
+ uribuilder = new URIBuilder(redirects.get(redirects.size() - 1));
+ String frag = uribuilder.getFragment();
+ // read interpreted fragment identifier from redirect locations
+ for (int i = redirects.size() - 1; frag == null && i >= 0; i--) {
+ frag = redirects.get(i).getFragment();
+ }
+ uribuilder.setFragment(frag);
+ }
+ // read interpreted fragment identifier from original request
+ if (uribuilder.getFragment() == null) {
+ uribuilder.setFragment(originalURI.getFragment());
+ }
+ // last target origin
+ if (target != null && !uribuilder.isAbsolute()) {
+ uribuilder.setScheme(target.getSchemeName());
+ uribuilder.setHost(target.getHostName());
+ uribuilder.setPort(target.getPort());
+ }
+ return uribuilder.build();
+ }
+
+ /**
* This class should not be instantiated.
*/
private URIUtils() {
Propchange: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/utils/URIUtils.java
------------------------------------------------------------------------------
svn:executable = *
Modified: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/client/utils/TestURIUtils.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/client/utils/TestURIUtils.java?rev=1487413&r1=1487412&r2=1487413&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/client/utils/TestURIUtils.java
(original)
+++ httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/client/utils/TestURIUtils.java
Wed May 29 09:04:54 2013
@@ -27,8 +27,19 @@
package org.apache.http.client.utils;
import java.net.URI;
+import java.util.Arrays;
import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.HttpVersion;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.impl.client.DefaultRedirectStrategy;
+import org.apache.http.message.BasicHttpResponse;
+import org.apache.http.protocol.HttpCoreContext;
import org.junit.Assert;
import org.junit.Test;
@@ -203,4 +214,68 @@ public class TestURIUtils {
URIUtils.extractHost(new URI("http://localhost:;sessionid=stuff/abcd")));
}
+ @Test
+ public void testHttpLocationWithRelativeFragment() throws Exception {
+ final HttpHost target = new HttpHost("localhost", -1, "http");
+ final URI requestURI = new URI("/stuff#blahblah");
+
+ final URI location = URIUtils.resolve(requestURI, target, null);
+ final URI expectedURI = new URIBuilder(requestURI)
+ .setHost(target.getHostName())
+ .setScheme(target.getSchemeName())
+ .build();
+ Assert.assertEquals(expectedURI, location);
+ }
+
+ @Test
+ public void testHttpLocationWithAbsoluteFragment() throws Exception {
+ final HttpHost target = new HttpHost("localhost", 80, "http");
+
+ final URI requestURI = new URIBuilder()
+ .setHost(target.getHostName())
+ .setScheme(target.getSchemeName())
+ .setPath("/stuff")
+ .setFragment("blahblah")
+ .build();
+
+ final URI location = URIUtils.resolve(requestURI, target, null);
+ final URI expectedURI = requestURI;
+ Assert.assertEquals(expectedURI, location);
+ }
+
+ @Test
+ public void testHttpLocationRedirect() throws Exception {
+ final HttpHost target = new HttpHost("localhost", -1, "http");
+ final URI requestURI = new URI("/People.htm#tim");
+
+ final URI redirect = new URI("http://localhost/people.html");
+
+ final URI location = URIUtils.resolve(requestURI, target, Arrays.asList(redirect));
+ final URI expectedURI = new URIBuilder()
+ .setHost(target.getHostName())
+ .setScheme(target.getSchemeName())
+ .setPath("/people.html")
+ .setFragment("tim")
+ .build();
+ Assert.assertEquals(expectedURI, location);
+ }
+
+ @Test
+ public void testHttpLocationWithRedirectFragment() throws Exception {
+ final HttpHost target = new HttpHost("localhost", -1, "http");
+ final URI requestURI = new URI("/~tim");
+
+ final URI redirect1 = new URI("http://localhost/People.htm#tim");
+ final URI redirect2 = new URI("http://localhost/people.html");
+
+ final URI location = URIUtils.resolve(requestURI, target, Arrays.asList(redirect1,
redirect2));
+ final URI expectedURI = new URIBuilder()
+ .setHost(target.getHostName())
+ .setScheme(target.getSchemeName())
+ .setPath("/people.html")
+ .setFragment("tim")
+ .build();
+ Assert.assertEquals(expectedURI, location);
+ }
+
}
Propchange: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/client/utils/TestURIUtils.java
------------------------------------------------------------------------------
svn:executable = *
Modified: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/integration/TestClientRequestExecution.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/integration/TestClientRequestExecution.java?rev=1487413&r1=1487412&r2=1487413&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/integration/TestClientRequestExecution.java
(original)
+++ httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/integration/TestClientRequestExecution.java
Wed May 29 09:04:54 2013
@@ -41,10 +41,12 @@ import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.NonRepeatableRequestException;
+import org.apache.http.client.URICollection;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.client.utils.URIUtils;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
@@ -256,8 +258,13 @@ public class TestClientRequestExecution
Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
EntityUtils.consume(response.getEntity());
- final HttpRequest request = (HttpRequest) context.getAttribute(HttpCoreContext.HTTP_REQUEST);
+ final HttpRequest request = context.getRequest();
Assert.assertEquals("/stuff", request.getRequestLine().getUri());
+
+ final URICollection redirectLocations = context.getRedirectLocations();
+ final URI location = URIUtils.resolve(uri, target,
+ redirectLocations != null ? redirectLocations.getAll() : null);
+ Assert.assertEquals(uri, location);
}
}
Propchange: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/integration/TestClientRequestExecution.java
------------------------------------------------------------------------------
svn:executable = *
Modified: httpcomponents/httpclient/trunk/src/docbkx/httpagent.xml
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/src/docbkx/httpagent.xml?rev=1487413&r1=1487412&r2=1487413&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/src/docbkx/httpagent.xml (original)
+++ httpcomponents/httpclient/trunk/src/docbkx/httpagent.xml Wed May 29 09:04:54 2013
@@ -206,6 +206,23 @@ System.out.println("Target host: " + tar
System.out.println("Final request URI: " + req.getURI()); // relative URI (no proxy used)
System.out.println("Final request method: " + req.getMethod());
]]></programlisting>
+ <para>The final interpreted absolute HTTP location can be built using the original
request
+ and the context. The utility method URIUtils.resolve(URI,HttpHost,URICollection)
+ can be used to build the interpreted absolute URI used to generate the final
request.
+ This method includes the last fragment identifier from the redirect requests
or
+ the original request.</para>
+ <programlisting><![CDATA[
+DefaultHttpClient httpclient = new DefaultHttpClient();
+
+HttpClientContext context = HttpClientContext.create();
+HttpGet httpget = new HttpGet("http://localhost:8080/");
+HttpResponse response = httpclient.execute(httpget, context);
+HttpHost target = context.getTargetHost();
+URICollection redirectLocations = context.getRedirectLocations();
+URI location = URIUtils.resolve(httpget.getURI(), target,
+ redirectLocations != null ? redirectLocations.getAll() : null);
+System.out.println("Final HTTP location: " + location.toASCIIString()); // absolute URI
+]]></programlisting>
</section>
<section>
<title>Compressed response content</title>
Propchange: httpcomponents/httpclient/trunk/src/docbkx/httpagent.xml
------------------------------------------------------------------------------
svn:executable = *
|