HTTPCLIENT-1542: Caching HttpClient uses absolute URIs for validation
Based on contribution by Joseph Walton <joe at kafsemo.org> git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1618324 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d5e17d7ec0
commit
683bb070fd
|
@ -27,6 +27,8 @@
|
||||||
package org.apache.http.impl.client.cache;
|
package org.apache.http.impl.client.cache;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -44,6 +46,7 @@ import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.HttpVersion;
|
import org.apache.http.HttpVersion;
|
||||||
|
import org.apache.http.ProtocolException;
|
||||||
import org.apache.http.ProtocolVersion;
|
import org.apache.http.ProtocolVersion;
|
||||||
import org.apache.http.RequestLine;
|
import org.apache.http.RequestLine;
|
||||||
import org.apache.http.annotation.ThreadSafe;
|
import org.apache.http.annotation.ThreadSafe;
|
||||||
|
@ -58,6 +61,7 @@ import org.apache.http.client.methods.HttpExecutionAware;
|
||||||
import org.apache.http.client.methods.HttpRequestWrapper;
|
import org.apache.http.client.methods.HttpRequestWrapper;
|
||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
import org.apache.http.client.utils.DateUtils;
|
import org.apache.http.client.utils.DateUtils;
|
||||||
|
import org.apache.http.client.utils.URIUtils;
|
||||||
import org.apache.http.conn.routing.HttpRoute;
|
import org.apache.http.conn.routing.HttpRoute;
|
||||||
import org.apache.http.impl.execchain.ClientExecChain;
|
import org.apache.http.impl.execchain.ClientExecChain;
|
||||||
import org.apache.http.message.BasicHttpResponse;
|
import org.apache.http.message.BasicHttpResponse;
|
||||||
|
@ -738,6 +742,14 @@ public class CachingExec implements ClientExecChain {
|
||||||
final HttpCacheEntry cacheEntry) throws IOException, HttpException {
|
final HttpCacheEntry cacheEntry) throws IOException, HttpException {
|
||||||
|
|
||||||
final HttpRequestWrapper conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry);
|
final HttpRequestWrapper conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry);
|
||||||
|
final URI uri = conditionalRequest.getURI();
|
||||||
|
if (uri != null) {
|
||||||
|
try {
|
||||||
|
request.setURI(URIUtils.rewriteURIForRoute(uri, route));
|
||||||
|
} catch (final URISyntaxException ex) {
|
||||||
|
throw new ProtocolException("Invalid URI: " + uri, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Date requestDate = getCurrentDate();
|
Date requestDate = getCurrentDate();
|
||||||
CloseableHttpResponse backendResponse = backend.execute(
|
CloseableHttpResponse backendResponse = backend.execute(
|
||||||
|
|
|
@ -93,6 +93,8 @@ public class TestHttpCacheJiraNumber1147 {
|
||||||
final HttpHost target = new HttpHost("somehost");
|
final HttpHost target = new HttpHost("somehost");
|
||||||
final HttpRoute route = new HttpRoute(target);
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
|
||||||
|
context.setTargetHost(target);
|
||||||
|
|
||||||
final Date now = new Date();
|
final Date now = new Date();
|
||||||
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ import java.util.Stack;
|
||||||
|
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.annotation.Immutable;
|
import org.apache.http.annotation.Immutable;
|
||||||
|
import org.apache.http.conn.routing.RouteInfo;
|
||||||
import org.apache.http.util.Args;
|
import org.apache.http.util.Args;
|
||||||
import org.apache.http.util.TextUtils;
|
import org.apache.http.util.TextUtils;
|
||||||
|
|
||||||
|
@ -195,6 +196,39 @@ public class URIUtils {
|
||||||
return uribuilder.build();
|
return uribuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A convenience method that optionally converts the original {@link java.net.URI} either
|
||||||
|
* to a relative or an absolute form as required by the specified route.
|
||||||
|
*
|
||||||
|
* @param uri
|
||||||
|
* original URI.
|
||||||
|
* @throws URISyntaxException
|
||||||
|
* If the resulting URI is invalid.
|
||||||
|
*
|
||||||
|
* @since 4.4
|
||||||
|
*/
|
||||||
|
public static URI rewriteURIForRoute(final URI uri, final RouteInfo route) throws URISyntaxException {
|
||||||
|
if (uri == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (route.getProxyHost() != null && !route.isTunnelled()) {
|
||||||
|
// Make sure the request URI is absolute
|
||||||
|
if (!uri.isAbsolute()) {
|
||||||
|
final HttpHost target = route.getTargetHost();
|
||||||
|
return rewriteURI(uri, target, true);
|
||||||
|
} else {
|
||||||
|
return rewriteURI(uri);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Make sure the request URI is relative
|
||||||
|
if (uri.isAbsolute()) {
|
||||||
|
return rewriteURI(uri, null, true);
|
||||||
|
} else {
|
||||||
|
return rewriteURI(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves a URI reference against a base URI. Work-around for bug in
|
* Resolves a URI reference against a base URI. Work-around for bug in
|
||||||
* java.net.URI (<http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>)
|
* java.net.URI (<http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>)
|
||||||
|
|
|
@ -87,29 +87,13 @@ public class ProtocolExec implements ClientExecChain {
|
||||||
void rewriteRequestURI(
|
void rewriteRequestURI(
|
||||||
final HttpRequestWrapper request,
|
final HttpRequestWrapper request,
|
||||||
final HttpRoute route) throws ProtocolException {
|
final HttpRoute route) throws ProtocolException {
|
||||||
try {
|
final URI uri = request.getURI();
|
||||||
URI uri = request.getURI();
|
if (uri != null) {
|
||||||
if (uri != null) {
|
try {
|
||||||
if (route.getProxyHost() != null && !route.isTunnelled()) {
|
request.setURI(URIUtils.rewriteURIForRoute(uri, route));
|
||||||
// Make sure the request URI is absolute
|
} catch (final URISyntaxException ex) {
|
||||||
if (!uri.isAbsolute()) {
|
throw new ProtocolException("Invalid URI: " + uri, ex);
|
||||||
final HttpHost target = route.getTargetHost();
|
|
||||||
uri = URIUtils.rewriteURI(uri, target, true);
|
|
||||||
} else {
|
|
||||||
uri = URIUtils.rewriteURI(uri);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Make sure the request URI is relative
|
|
||||||
if (uri.isAbsolute()) {
|
|
||||||
uri = URIUtils.rewriteURI(uri, null, true);
|
|
||||||
} else {
|
|
||||||
uri = URIUtils.rewriteURI(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.setURI(uri);
|
|
||||||
}
|
}
|
||||||
} catch (final URISyntaxException ex) {
|
|
||||||
throw new ProtocolException("Invalid URI: " + request.getRequestLine().getUri(), ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ import java.net.URI;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
|
import org.apache.http.conn.routing.HttpRoute;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -100,6 +101,34 @@ public class TestURIUtils {
|
||||||
URI.create("http://thishost:80/stuff#crap"), target, true).toString());
|
URI.create("http://thishost:80/stuff#crap"), target, true).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRewriteForRoute() throws Exception {
|
||||||
|
|
||||||
|
final HttpHost target1 = new HttpHost("foo", 80);
|
||||||
|
final HttpHost target2 = new HttpHost("foo", 443, "https");
|
||||||
|
final HttpHost proxy = new HttpHost("bar", 8888);
|
||||||
|
|
||||||
|
// Direct route
|
||||||
|
Assert.assertEquals(new URI("/test"), URIUtils
|
||||||
|
.rewriteURIForRoute(new URI("http://foo/test"), new HttpRoute(target1)));
|
||||||
|
|
||||||
|
// Direct route
|
||||||
|
Assert.assertEquals(new URI("/"), URIUtils
|
||||||
|
.rewriteURIForRoute(new URI(""), new HttpRoute(target1)));
|
||||||
|
|
||||||
|
// Via proxy
|
||||||
|
Assert.assertEquals(new URI("http://foo/test"), URIUtils
|
||||||
|
.rewriteURIForRoute(new URI("http://foo/test"), new HttpRoute(target1, proxy)));
|
||||||
|
|
||||||
|
// Via proxy
|
||||||
|
Assert.assertEquals(new URI("http://foo:80/test"), URIUtils
|
||||||
|
.rewriteURIForRoute(new URI("/test"), new HttpRoute(target1, proxy)));
|
||||||
|
|
||||||
|
// Via proxy tunnel
|
||||||
|
Assert.assertEquals(new URI("/test"), URIUtils
|
||||||
|
.rewriteURIForRoute(new URI("https://foo:443/test"), new HttpRoute(target2, null, proxy, true)));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNormalization() {
|
public void testNormalization() {
|
||||||
Assert.assertEquals("example://a/b/c/%7Bfoo%7D", URIUtils.resolve(this.baseURI, "eXAMPLE://a/./b/../b/%63/%7bfoo%7d").toString());
|
Assert.assertEquals("example://a/b/c/%7Bfoo%7D", URIUtils.resolve(this.baseURI, "eXAMPLE://a/./b/../b/%63/%7bfoo%7d").toString());
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.http.impl.execchain;
|
package org.apache.http.impl.execchain;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
import org.apache.http.HttpException;
|
import org.apache.http.HttpException;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.auth.AuthScope;
|
import org.apache.http.auth.AuthScope;
|
||||||
|
@ -47,9 +50,6 @@ import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
@SuppressWarnings({"static-access"}) // test code
|
@SuppressWarnings({"static-access"}) // test code
|
||||||
public class TestProtocolExec {
|
public class TestProtocolExec {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue