You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2012/12/20 17:56:43 UTC
svn commit: r1424589 - in /httpcomponents/httpclient/trunk: ./
httpclient-cache/src/main/java/org/apache/http/impl/client/cache/
httpclient-cache/src/test/java/org/apache/http/impl/client/cache/
Author: olegk
Date: Thu Dec 20 16:56:41 2012
New Revision: 1424589
URL: http://svn.apache.org/viewvc?rev=1424589&view=rev
Log:
HTTPCLIENT-1250: Allow query string to be ignored when determining cacheability for HTTP 1.0 responses
Contributed by Don Brown <mrdon at twdata.org>
Modified:
httpcomponents/httpclient/trunk/RELEASE_NOTES.txt
httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java
httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java
httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java
httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java
httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java
httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestResponseCachingPolicy.java
Modified: httpcomponents/httpclient/trunk/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/RELEASE_NOTES.txt?rev=1424589&r1=1424588&r2=1424589&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/RELEASE_NOTES.txt (original)
+++ httpcomponents/httpclient/trunk/RELEASE_NOTES.txt Thu Dec 20 16:56:41 2012
@@ -1,6 +1,10 @@
Changes in trunk
-------------------
+* [HTTPCLIENT-1250] Allow query string to be ignored when determining cacheability for HTTP 1.0
+ responses.
+ Contributed by Don Brown <mrdon at twdata.org>
+
* [HTTPCLIENT-1284] HttpClient incorrectly generates Host header when physical connection
route differs from the host name specified in the request URI.
Contributed by Oleg Kalnichevski <olegk at apache.org>
Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java?rev=1424589&r1=1424588&r2=1424589&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java Thu Dec 20 16:56:41 2012
@@ -145,6 +145,7 @@ public class CacheConfig implements Clon
private int asynchronousWorkersCore;
private int asynchronousWorkerIdleLifetimeSecs;
private int revalidationQueueSize;
+ private boolean neverCacheHTTP10ResponsesWithQuery;
/**
* @deprecated (4.3) use {@link Builder}.
@@ -176,7 +177,8 @@ public class CacheConfig implements Clon
int asynchronousWorkersMax,
int asynchronousWorkersCore,
int asynchronousWorkerIdleLifetimeSecs,
- int revalidationQueueSize) {
+ int revalidationQueueSize,
+ boolean neverCacheHTTP10ResponsesWithQuery) {
super();
this.maxObjectSize = maxObjectSize;
this.maxCacheEntries = maxCacheEntries;
@@ -241,6 +243,15 @@ public class CacheConfig implements Clon
}
/**
+ * Returns whether the cache will never cache HTTP 1.0 responses with a query string or not.
+ * @return {@code true} to not cache query string responses, {@code false} to cache if explicit cache headers are
+ * found
+ */
+ public boolean isNeverCacheHTTP10ResponsesWithQuery() {
+ return neverCacheHTTP10ResponsesWithQuery;
+ }
+
+ /**
* Returns the maximum number of cache entries the cache will retain.
*/
public int getMaxCacheEntries() {
@@ -470,6 +481,7 @@ public class CacheConfig implements Clon
private int asynchronousWorkersCore;
private int asynchronousWorkerIdleLifetimeSecs;
private int revalidationQueueSize;
+ private boolean neverCacheHTTP10ResponsesWithQuery;
Builder() {
this.maxObjectSize = DEFAULT_MAX_OBJECT_SIZE_BYTES;
@@ -602,6 +614,18 @@ public class CacheConfig implements Clon
return this;
}
+ /**
+ * Sets whether the cache should never cache HTTP 1.0 responses with a query string or not.
+ * @param neverCache1_0ResponsesWithQueryString true to never cache responses with a query
+ * string, false to cache if explicit cache headers are found. Set this to {@code true}
+ * to better emulate IE, which also never caches responses, regardless of what caching
+ * headers may be present.
+ */
+ public Builder setNeverCache1_0ResponsesWithQueryString(boolean b) {
+ this.neverCacheHTTP10ResponsesWithQuery = b;
+ return this;
+ }
+
public CacheConfig build() {
return new CacheConfig(
maxObjectSize,
@@ -614,7 +638,8 @@ public class CacheConfig implements Clon
asynchronousWorkersMax,
asynchronousWorkersCore,
asynchronousWorkerIdleLifetimeSecs,
- revalidationQueueSize);
+ revalidationQueueSize,
+ neverCacheHTTP10ResponsesWithQuery);
}
}
@@ -632,6 +657,7 @@ public class CacheConfig implements Clon
.append(", asynchronousWorkersCore=").append(this.asynchronousWorkersCore)
.append(", asynchronousWorkerIdleLifetimeSecs=").append(this.asynchronousWorkerIdleLifetimeSecs)
.append(", revalidationQueueSize=").append(this.revalidationQueueSize)
+ .append(", neverCacheHTTP10ResponsesWithQuery=").append(this.neverCacheHTTP10ResponsesWithQuery)
.append("]");
return builder.toString();
}
Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java?rev=1424589&r1=1424588&r2=1424589&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java Thu Dec 20 16:56:41 2012
@@ -133,7 +133,8 @@ public class CachingExec implements Clie
this.responseCompliance = new ResponseProtocolCompliance();
this.requestCompliance = new RequestProtocolCompliance();
this.responseCachingPolicy = new ResponseCachingPolicy(
- this.cacheConfig.getMaxObjectSize(), this.cacheConfig.isSharedCache());
+ this.cacheConfig.getMaxObjectSize(), this.cacheConfig.isSharedCache(),
+ this.cacheConfig.isNeverCacheHTTP10ResponsesWithQuery());
this.asynchRevalidator = makeAsynchronousValidator(config);
}
Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java?rev=1424589&r1=1424588&r2=1424589&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java Thu Dec 20 16:56:41 2012
@@ -174,7 +174,8 @@ public class CachingHttpClient implement
this.backend = client;
this.responseCache = cache;
this.validityPolicy = new CacheValidityPolicy();
- this.responseCachingPolicy = new ResponseCachingPolicy(maxObjectSizeBytes, sharedCache);
+ this.responseCachingPolicy = new ResponseCachingPolicy(maxObjectSizeBytes, sharedCache,
+ config.isNeverCacheHTTP10ResponsesWithQuery());
this.responseGenerator = new CachedHttpResponseGenerator(this.validityPolicy);
this.cacheableRequestPolicy = new CacheableRequestPolicy();
this.suitabilityChecker = new CachedResponseSuitabilityChecker(this.validityPolicy, config);
Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java?rev=1424589&r1=1424588&r2=1424589&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java Thu Dec 20 16:56:41 2012
@@ -56,6 +56,7 @@ class ResponseCachingPolicy {
private final long maxObjectSizeBytes;
private final boolean sharedCache;
+ private final boolean neverCache1_0ResponsesWithQueryString;
private final Log log = LogFactory.getLog(getClass());
private static final Set<Integer> cacheableStatuses =
new HashSet<Integer>(Arrays.asList(HttpStatus.SC_OK,
@@ -66,7 +67,6 @@ class ResponseCachingPolicy {
private static final Set<Integer> uncacheableStatuses =
new HashSet<Integer>(Arrays.asList(HttpStatus.SC_PARTIAL_CONTENT,
HttpStatus.SC_SEE_OTHER));
-
/**
* Define a cache policy that limits the size of things that should be stored
* in the cache to a maximum of {@link HttpResponse} bytes in size.
@@ -74,10 +74,15 @@ class ResponseCachingPolicy {
* @param maxObjectSizeBytes the size to limit items into the cache
* @param sharedCache whether to behave as a shared cache (true) or a
* non-shared/private cache (false)
+ * @param neverCache1_0ResponsesWithQueryString true to never cache HTTP 1.0 responses with a query string, false
+ * to cache if explicit cache headers are found.
*/
- public ResponseCachingPolicy(long maxObjectSizeBytes, boolean sharedCache) {
+ public ResponseCachingPolicy(long maxObjectSizeBytes, boolean sharedCache,
+ boolean neverCache1_0ResponsesWithQueryString
+ ) {
this.maxObjectSizeBytes = maxObjectSizeBytes;
this.sharedCache = sharedCache;
+ this.neverCache1_0ResponsesWithQueryString = neverCache1_0ResponsesWithQueryString;
}
/**
@@ -216,10 +221,14 @@ class ResponseCachingPolicy {
return false;
}
- if (request.getRequestLine().getUri().contains("?") &&
- (!isExplicitlyCacheable(response) || from1_0Origin(response))) {
- log.debug("Response was not cacheable.");
- return false;
+ if (request.getRequestLine().getUri().contains("?")) {
+ if (neverCache1_0ResponsesWithQueryString && from1_0Origin(response)) {
+ log.debug("Response was not cacheable as it had a query string.");
+ return false;
+ } else if (!isExplicitlyCacheable(response)) {
+ log.debug("Response was not cacheable as it is missing explicit caching headers.");
+ return false;
+ }
}
if (expiresHeaderLessOrEqualToDateHeaderAndNoCacheControl(response)) {
Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java?rev=1424589&r1=1424588&r2=1424589&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java Thu Dec 20 16:56:41 2012
@@ -65,7 +65,6 @@ import org.junit.Test;
*/
public class TestProtocolRecommendations extends AbstractProtocolTest {
- private Date tenSecondsFromNow;
private Date now;
private Date tenSecondsAgo;
private Date twoMinutesAgo;
@@ -77,7 +76,6 @@ public class TestProtocolRecommendations
now = new Date();
tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
twoMinutesAgo = new Date(now.getTime() - 2 * 60 * 1000L);
- tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
}
/* "identity: The default (identity) encoding; the use of no
@@ -1445,18 +1443,8 @@ public class TestProtocolRecommendations
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.9
*/
@Test
- public void responseToGetWithQueryFrom1_0OriginIsNotCached()
+ public void responseToGetWithQueryFrom1_0OriginAndNoExpiresIsNotCached()
throws Exception {
- HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
- new HttpGet("http://foo.example.com/bar?baz=quux"));
- HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
- resp1.setEntity(HttpTestUtils.makeBody(200));
- resp1.setHeader("Content-Length","200");
- resp1.setHeader("Date", formatDate(now));
- resp1.setHeader("Expires", formatDate(tenSecondsFromNow));
-
- backendExpectsAnyRequestAndReturn(resp1);
-
HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
new HttpGet("http://foo.example.com/bar?baz=quux"));
HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
@@ -1467,25 +1455,13 @@ public class TestProtocolRecommendations
backendExpectsAnyRequestAndReturn(resp2);
replayMocks();
- impl.execute(route, req1);
impl.execute(route, req2);
verifyMocks();
}
@Test
- public void responseToGetWithQueryFrom1_0OriginVia1_1ProxyIsNotCached()
+ public void responseToGetWithQueryFrom1_0OriginVia1_1ProxyAndNoExpiresIsNotCached()
throws Exception {
- HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
- new HttpGet("http://foo.example.com/bar?baz=quux"));
- HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
- resp1.setEntity(HttpTestUtils.makeBody(200));
- resp1.setHeader("Content-Length","200");
- resp1.setHeader("Date", formatDate(now));
- resp1.setHeader("Expires", formatDate(tenSecondsFromNow));
- resp1.setHeader("Via","1.0 someproxy");
-
- backendExpectsAnyRequestAndReturn(resp1);
-
HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
new HttpGet("http://foo.example.com/bar?baz=quux"));
HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
@@ -1497,7 +1473,6 @@ public class TestProtocolRecommendations
backendExpectsAnyRequestAndReturn(resp2);
replayMocks();
- impl.execute(route, req1);
impl.execute(route, req2);
verifyMocks();
}
Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestResponseCachingPolicy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestResponseCachingPolicy.java?rev=1424589&r1=1424588&r2=1424589&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestResponseCachingPolicy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestResponseCachingPolicy.java Thu Dec 20 16:56:41 2012
@@ -61,7 +61,7 @@ public class TestResponseCachingPolicy {
sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
- policy = new ResponseCachingPolicy(0, true);
+ policy = new ResponseCachingPolicy(0, true, false);
request = new BasicHttpRequest("GET","/",HTTP_1_1);
response = new BasicHttpResponse(
new BasicStatusLine(HTTP_1_1, HttpStatus.SC_OK, ""));
@@ -83,7 +83,7 @@ public class TestResponseCachingPolicy {
@Test
public void testResponsesToRequestsWithAuthorizationHeadersAreCacheableByNonSharedCache() {
- policy = new ResponseCachingPolicy(0, false);
+ policy = new ResponseCachingPolicy(0, false, false);
request = new BasicHttpRequest("GET","/",HTTP_1_1);
request.setHeader("Authorization","Basic dXNlcjpwYXNzd2Q=");
Assert.assertTrue(policy.isResponseCacheable(request,response));
@@ -225,7 +225,7 @@ public class TestResponseCachingPolicy {
@Test
public void test200ResponseWithPrivateCacheControlIsCacheableByNonSharedCache() {
- policy = new ResponseCachingPolicy(0, false);
+ policy = new ResponseCachingPolicy(0, false, false);
response.setStatusCode(HttpStatus.SC_OK);
response.setHeader("Cache-Control", "private");
Assert.assertTrue(policy.isResponseCacheable("GET", response));
@@ -384,6 +384,13 @@ public class TestResponseCachingPolicy {
}
@Test
+ public void testResponsesToGETWithQueryParamsButNoExplicitCachingAreNotCacheableEvenWhen1_0QueryCachingDisabled() {
+ policy = new ResponseCachingPolicy(0, true, true);
+ request = new BasicHttpRequest("GET", "/foo?s=bar");
+ Assert.assertFalse(policy.isResponseCacheable(request, response));
+ }
+
+ @Test
public void testResponsesToGETWithQueryParamsAndExplicitCachingAreCacheable() {
request = new BasicHttpRequest("GET", "/foo?s=bar");
response.setHeader("Date", formatDate(now));
@@ -392,6 +399,15 @@ public class TestResponseCachingPolicy {
}
@Test
+ public void testResponsesToGETWithQueryParamsAndExplicitCachingAreCacheableEvenWhen1_0QueryCachingDisabled() {
+ policy = new ResponseCachingPolicy(0, true, true);
+ request = new BasicHttpRequest("GET", "/foo?s=bar");
+ response.setHeader("Date", formatDate(now));
+ response.setHeader("Expires", formatDate(tenSecondsFromNow));
+ Assert.assertTrue(policy.isResponseCacheable(request, response));
+ }
+
+ @Test
public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheable() {
request = new BasicHttpRequest("GET", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
@@ -399,7 +415,25 @@ public class TestResponseCachingPolicy {
}
@Test
- public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithExpires() {
+ public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithSetting() {
+ policy = new ResponseCachingPolicy(0, true, true);
+ request = new BasicHttpRequest("GET", "/foo?s=bar");
+ response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
+ Assert.assertFalse(policy.isResponseCacheable(request, response));
+ }
+
+ @Test
+ public void getsWithQueryParametersDirectlyFrom1_0OriginsAreCacheableWithExpires() {
+ request = new BasicHttpRequest("GET", "/foo?s=bar");
+ response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
+ response.setHeader("Date", formatDate(now));
+ response.setHeader("Expires", formatDate(tenSecondsFromNow));
+ Assert.assertTrue(policy.isResponseCacheable(request, response));
+ }
+
+ @Test
+ public void getsWithQueryParametersDirectlyFrom1_0OriginsCanBeNotCacheableEvenWithExpires() {
+ policy = new ResponseCachingPolicy(0, true, true);
request = new BasicHttpRequest("GET", "/foo?s=bar");
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
response.setHeader("Date", formatDate(now));
@@ -415,7 +449,19 @@ public class TestResponseCachingPolicy {
}
@Test
- public void getsWithQueryParametersFrom1_0OriginsViaProxiesAreNotCacheableEvenWithExpires() {
+ public void getsWithQueryParametersFrom1_0OriginsViaProxiesAreCacheableWithExpires() {
+ request = new BasicHttpRequest("GET", "/foo?s=bar");
+ Date now = new Date();
+ Date tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
+ response.setHeader("Date", formatDate(now));
+ response.setHeader("Expires", formatDate(tenSecondsFromNow));
+ response.setHeader("Via", "1.0 someproxy");
+ Assert.assertTrue(policy.isResponseCacheable(request, response));
+ }
+
+ @Test
+ public void getsWithQueryParametersFrom1_0OriginsViaProxiesCanNotBeCacheableEvenWithExpires() {
+ policy = new ResponseCachingPolicy(0, true, true);
request = new BasicHttpRequest("GET", "/foo?s=bar");
Date now = new Date();
Date tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
@@ -426,7 +472,17 @@ public class TestResponseCachingPolicy {
}
@Test
- public void getsWithQueryParametersFrom1_0OriginsViaExplicitProxiesAreNotCacheableEvenWithExpires() {
+ public void getsWithQueryParametersFrom1_0OriginsViaExplicitProxiesAreCacheableWithExpires() {
+ request = new BasicHttpRequest("GET", "/foo?s=bar");
+ response.setHeader("Date", formatDate(now));
+ response.setHeader("Expires", formatDate(tenSecondsFromNow));
+ response.setHeader("Via", "HTTP/1.0 someproxy");
+ Assert.assertTrue(policy.isResponseCacheable(request, response));
+ }
+
+ @Test
+ public void getsWithQueryParametersFrom1_0OriginsViaExplicitProxiesCanNotBeCacheableEvenWithExpires() {
+ policy = new ResponseCachingPolicy(0, true, true);
request = new BasicHttpRequest("GET", "/foo?s=bar");
response.setHeader("Date", formatDate(now));
response.setHeader("Expires", formatDate(tenSecondsFromNow));