Responses from HTTP/1.0 origins to requests containing query parameters
SHOULD NOT be taken from a cache. http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.9 git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1057715 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
020d303ec5
commit
e95a80b7a2
|
@ -201,7 +201,8 @@ class ResponseCachingPolicy {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (request.getRequestLine().getUri().contains("?") && !isExplicitlyCacheable(response)) {
|
||||
if (request.getRequestLine().getUri().contains("?") &&
|
||||
(!isExplicitlyCacheable(response) || from1_0Origin(response))) {
|
||||
log.debug("Response was not cacheable.");
|
||||
return false;
|
||||
}
|
||||
|
@ -220,6 +221,21 @@ class ResponseCachingPolicy {
|
|||
return isResponseCacheable(method, response);
|
||||
}
|
||||
|
||||
private boolean from1_0Origin(HttpResponse response) {
|
||||
Header via = response.getFirstHeader("Via");
|
||||
if (via != null) {
|
||||
for(HeaderElement elt : via.getElements()) {
|
||||
String proto = elt.toString().split("\\s")[0];
|
||||
if (proto.contains("/")) {
|
||||
return proto.equals("HTTP/1.0");
|
||||
} else {
|
||||
return proto.equals("1.0");
|
||||
}
|
||||
}
|
||||
}
|
||||
return HttpVersion.HTTP_1_0.equals(response.getProtocolVersion());
|
||||
}
|
||||
|
||||
private boolean requestProtocolGreaterThanAccepted(HttpRequest req) {
|
||||
return req.getProtocolVersion().compareToVersion(HttpVersion.HTTP_1_1) > 0;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ import org.junit.Test;
|
|||
*/
|
||||
public class TestProtocolRecommendations extends AbstractProtocolTest {
|
||||
|
||||
private Date tenSecondsFromNow;
|
||||
private Date now;
|
||||
private Date tenSecondsAgo;
|
||||
|
||||
|
@ -68,6 +69,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
super.setUp();
|
||||
now = new Date();
|
||||
tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
|
||||
tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
|
||||
}
|
||||
|
||||
/* "identity: The default (identity) encoding; the use of no
|
||||
|
@ -1078,4 +1080,66 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
impl.execute(host, req3);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
/*
|
||||
* "This specifically means that responses from HTTP/1.0 servers for such
|
||||
* URIs [those containing a '?' in the rel_path part] SHOULD NOT be taken
|
||||
* from a cache."
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.9
|
||||
*/
|
||||
@Test
|
||||
public void responseToGetWithQueryFrom1_0OriginIsNotCached()
|
||||
throws Exception {
|
||||
HttpRequest req1 = 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));
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = new HttpGet("http://foo.example.com/bar?baz=quux");
|
||||
HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
|
||||
resp2.setEntity(HttpTestUtils.makeBody(200));
|
||||
resp2.setHeader("Content-Length","200");
|
||||
resp2.setHeader("Date", formatDate(now));
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
impl.execute(host, req2);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseToGetWithQueryFrom1_0OriginVia1_1ProxyIsNotCached()
|
||||
throws Exception {
|
||||
HttpRequest req1 = 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");
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp1);
|
||||
|
||||
HttpRequest req2 = new HttpGet("http://foo.example.com/bar?baz=quux");
|
||||
HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
|
||||
resp2.setEntity(HttpTestUtils.makeBody(200));
|
||||
resp2.setHeader("Content-Length","200");
|
||||
resp2.setHeader("Date", formatDate(now));
|
||||
resp2.setHeader("Via","1.0 someproxy");
|
||||
|
||||
backendExpectsAnyRequest().andReturn(resp2);
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, req1);
|
||||
impl.execute(host, req2);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,8 +32,9 @@ import java.util.Random;
|
|||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.HttpVersion;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.impl.cookie.DateUtils;
|
||||
import static org.apache.http.impl.cookie.DateUtils.formatDate;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.apache.http.message.BasicHttpResponse;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
|
@ -57,7 +58,7 @@ public class TestResponseCachingPolicy {
|
|||
request = new BasicHttpRequest("GET","/",HTTP_1_1);
|
||||
response = new BasicHttpResponse(
|
||||
new BasicStatusLine(HTTP_1_1, HttpStatus.SC_OK, ""));
|
||||
response.setHeader("Date", DateUtils.formatDate(new Date()));
|
||||
response.setHeader("Date", formatDate(new Date()));
|
||||
response.setHeader("Content-Length", "0");
|
||||
}
|
||||
|
||||
|
@ -163,7 +164,7 @@ public class TestResponseCachingPolicy {
|
|||
public void testNon206WithExplicitExpiresIsCacheable() {
|
||||
int status = getRandomStatus();
|
||||
response.setStatusCode(status);
|
||||
response.setHeader("Expires", DateUtils.formatDate(new Date()));
|
||||
response.setHeader("Expires", formatDate(new Date()));
|
||||
Assert.assertTrue(policy.isResponseCacheable("GET", response));
|
||||
}
|
||||
|
||||
|
@ -275,7 +276,7 @@ public class TestResponseCachingPolicy {
|
|||
|
||||
response = new BasicHttpResponse(
|
||||
new BasicStatusLine(HTTP_1_1, HttpStatus.SC_OK, ""));
|
||||
response.setHeader("Date", DateUtils.formatDate(new Date()));
|
||||
response.setHeader("Date", formatDate(new Date()));
|
||||
response.addHeader("Cache-Control", "no-transform");
|
||||
response.setHeader("Content-Length", "0");
|
||||
|
||||
|
@ -333,8 +334,8 @@ public class TestResponseCachingPolicy {
|
|||
public void testResponsesWithMultipleDateHeadersAreNotCacheable() {
|
||||
Date now = new Date();
|
||||
Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
||||
response.addHeader("Date", DateUtils.formatDate(now));
|
||||
response.addHeader("Date", DateUtils.formatDate(sixSecondsAgo));
|
||||
response.addHeader("Date", formatDate(now));
|
||||
response.addHeader("Date", formatDate(sixSecondsAgo));
|
||||
Assert.assertFalse(policy.isResponseCacheable("GET", response));
|
||||
}
|
||||
|
||||
|
@ -348,8 +349,8 @@ public class TestResponseCachingPolicy {
|
|||
public void testResponsesWithMultipleExpiresHeadersAreNotCacheable() {
|
||||
Date now = new Date();
|
||||
Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
|
||||
response.addHeader("Expires", DateUtils.formatDate(now));
|
||||
response.addHeader("Expires", DateUtils.formatDate(sixSecondsAgo));
|
||||
response.addHeader("Expires", formatDate(now));
|
||||
response.addHeader("Expires", formatDate(sixSecondsAgo));
|
||||
Assert.assertFalse(policy.isResponseCacheable("GET", response));
|
||||
}
|
||||
|
||||
|
@ -380,7 +381,66 @@ public class TestResponseCachingPolicy {
|
|||
@Test
|
||||
public void testResponsesToGETWithQueryParamsAndExplicitCachingAreCacheable() {
|
||||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
response.setHeader("Expires", DateUtils.formatDate(new Date()));
|
||||
response.setHeader("Expires", formatDate(new Date()));
|
||||
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");
|
||||
Assert.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getsWithQueryParametersDirectlyFrom1_0OriginsAreNotCacheableEvenWithExpires() {
|
||||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
|
||||
Date now = new Date();
|
||||
Date tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
|
||||
response.setHeader("Date", formatDate(now));
|
||||
response.setHeader("Expires", formatDate(tenSecondsFromNow));
|
||||
Assert.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getsWithQueryParametersFrom1_0OriginsViaProxiesAreNotCacheable() {
|
||||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
response.setHeader("Via", "1.0 someproxy");
|
||||
Assert.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getsWithQueryParametersFrom1_0OriginsViaProxiesAreNotCacheableEvenWithExpires() {
|
||||
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.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getsWithQueryParametersFrom1_0OriginsViaExplicitProxiesAreNotCacheableEvenWithExpires() {
|
||||
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", "HTTP/1.0 someproxy");
|
||||
Assert.assertFalse(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getsWithQueryParametersFrom1_1OriginsVia1_0ProxiesAreCacheableWithExpires() {
|
||||
request = new BasicHttpRequest("GET", "/foo?s=bar");
|
||||
Date now = new Date();
|
||||
Date tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
|
||||
response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK");
|
||||
response.setHeader("Date", formatDate(now));
|
||||
response.setHeader("Expires", formatDate(tenSecondsFromNow));
|
||||
response.setHeader("Via", "1.1 someproxy");
|
||||
Assert.assertTrue(policy.isResponseCacheable(request, response));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue