From e82184af366fb7a5fc73938c832d5327c0eb89f2 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 22 Sep 2010 14:52:44 +0000 Subject: [PATCH] HTTPCLIENT-997: cache module should handle out-of-order validations properly and unconditionally refresh Contributed by Jonathan Moore git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1000011 13f79535-47bb-0310-9956-ffa450edef68 --- .../impl/client/cache/CacheInvalidator.java | 37 +-- .../impl/client/cache/CachingHttpClient.java | 54 ++++- .../cache/ConditionalRequestBuilder.java | 26 ++ .../client/cache/AbstractProtocolTest.java | 19 +- .../http/impl/client/cache/HttpTestUtils.java | 10 + .../client/cache/TestCacheInvalidator.java | 16 +- .../client/cache/TestCachingHttpClient.java | 223 ++++++++++++++---- .../cache/TestConditionalRequestBuilder.java | 107 +++++++++ .../cache/TestProtocolRecommendations.java | 136 ++++++++++- .../cache/TestProtocolRequirements.java | 220 ++++++++--------- .../TestEhcacheProtcolRequirements.java | 0 .../TestEhcacheProtocolRequirements.java | 2 +- 12 files changed, 621 insertions(+), 229 deletions(-) delete mode 100644 httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtcolRequirements.java diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java index d104c56a8..f152333c8 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java @@ -33,7 +33,6 @@ import java.net.URL; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.Header; -import org.apache.http.HeaderElement; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.annotation.ThreadSafe; @@ -145,45 +144,11 @@ class CacheInvalidator { protected boolean requestShouldNotBeCached(HttpRequest req) { String method = req.getRequestLine().getMethod(); - return notGetOrHeadRequest(method) || containsCacheControlHeader(req) - || containsPragmaHeader(req); + return notGetOrHeadRequest(method); } private boolean notGetOrHeadRequest(String method) { return !(HeaderConstants.GET_METHOD.equals(method) || HeaderConstants.HEAD_METHOD .equals(method)); } - - private boolean containsPragmaHeader(HttpRequest req) { - return req.getFirstHeader(HeaderConstants.PRAGMA) != null; - } - - private boolean containsCacheControlHeader(HttpRequest request) { - Header[] cacheControlHeaders = request.getHeaders(HeaderConstants.CACHE_CONTROL); - - if (cacheControlHeaders == null) { - return false; - } - - for (Header cacheControl : cacheControlHeaders) { - HeaderElement[] cacheControlElements = cacheControl.getElements(); - if (cacheControlElements == null) { - return false; - } - - for (HeaderElement cacheControlElement : cacheControlElements) { - if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(cacheControlElement - .getName())) { - return true; - } - - if (HeaderConstants.CACHE_CONTROL_NO_STORE.equalsIgnoreCase(cacheControlElement - .getName())) { - return true; - } - } - } - - return false; - } } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java index e3ab5068b..10322d74f 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java @@ -56,6 +56,8 @@ import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.cookie.DateParseException; +import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.BasicHttpResponse; import org.apache.http.params.HttpParams; import org.apache.http.protocol.HttpContext; @@ -529,12 +531,34 @@ public class CachingHttpClient implements HttpClient { HttpContext context, HttpCacheEntry cacheEntry) throws IOException, ProtocolException { HttpRequest conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry); + Date requestDate = getCurrentDate(); - HttpResponse backendResponse = backend.execute(target, conditionalRequest, context); - Date responseDate = getCurrentDate(); + + final Header entryDateHeader = cacheEntry.getFirstHeader("Date"); + final Header responseDateHeader = backendResponse.getFirstHeader("Date"); + if (entryDateHeader != null && responseDateHeader != null) { + try { + Date entryDate = DateUtils.parseDate(entryDateHeader.getValue()); + Date respDate = DateUtils.parseDate(responseDateHeader.getValue()); + if (respDate.before(entryDate)) { + HttpRequest unconditional = conditionalRequestBuilder + .buildUnconditionalRequest(request, cacheEntry); + requestDate = getCurrentDate(); + backendResponse = backend.execute(target, unconditional, context); + responseDate = getCurrentDate(); + } + } catch (DateParseException e) { + // either backend response or cached entry did not have a valid + // Date header, so we can't tell if they are out of order + // according to the origin clock; thus we can skip the + // unconditional retry recommended in 13.2.6 of RFC 2616. + } + } + + int statusCode = backendResponse.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) { cacheUpdates.getAndIncrement(); @@ -558,14 +582,32 @@ public class CachingHttpClient implements HttpClient { responseCompliance.ensureProtocolCompliance(request, backendResponse); boolean cacheable = responseCachingPolicy.isResponseCacheable(request, backendResponse); - - if (cacheable) { + if (cacheable && + !alreadyHaveNewerCacheEntry(target, request, backendResponse)) { return responseCache.cacheAndReturnResponse(target, request, backendResponse, requestDate, responseDate); } - - responseCache.flushCacheEntriesFor(target, request); + if (!cacheable) { + responseCache.flushCacheEntriesFor(target, request); + } return backendResponse; } + private boolean alreadyHaveNewerCacheEntry(HttpHost target, HttpRequest request, + HttpResponse backendResponse) throws IOException { + HttpCacheEntry existing = responseCache.getCacheEntry(target, request); + if (existing == null) return false; + Header entryDateHeader = existing.getFirstHeader("Date"); + if (entryDateHeader == null) return false; + Header responseDateHeader = backendResponse.getFirstHeader("Date"); + if (responseDateHeader == null) return false; + try { + Date entryDate = DateUtils.parseDate(entryDateHeader.getValue()); + Date responseDate = DateUtils.parseDate(responseDateHeader.getValue()); + return responseDate.before(entryDate); + } catch (DateParseException e) { + } + return false; + } + } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java index 6bf9245cf..71bbbe79b 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java @@ -79,4 +79,30 @@ class ConditionalRequestBuilder { } + /** + * Returns a request to unconditionally validate a cache entry with + * the origin. In certain cases (due to multiple intervening caches) + * our cache may actually receive a response to a normal conditional + * validation where the Date header is actually older than that of + * our current cache entry. In this case, the protocol recommendation + * is to retry the validation and force syncup with the origin. + * @param request client request we are trying to satisfy + * @param entry existing cache entry we are trying to validate + * @return an unconditional validation request + * @throws ProtocolException + */ + public HttpRequest buildUnconditionalRequest(HttpRequest request, + HttpCacheEntry entry) throws ProtocolException { + RequestWrapper wrapped = new RequestWrapper(request); + wrapped.resetHeaders(); + wrapped.addHeader("Cache-Control","no-cache"); + wrapped.addHeader("Pragma","no-cache"); + wrapped.removeHeaders("If-Range"); + wrapped.removeHeaders("If-Match"); + wrapped.removeHeaders("If-None-Match"); + wrapped.removeHeaders("If-Unmodified-Since"); + wrapped.removeHeaders("If-Modified-Since"); + return wrapped; + } + } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java index fe1a12233..32cedb20d 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/AbstractProtocolTest.java @@ -1,18 +1,14 @@ package org.apache.http.impl.client.cache; -import java.util.Date; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.client.cache.HttpCache; -import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.BasicHttpRequest; -import org.apache.http.message.BasicHttpResponse; import org.apache.http.protocol.HttpContext; import org.easymock.IExpectationSetters; import org.easymock.classextension.EasyMock; @@ -46,7 +42,7 @@ public abstract class AbstractProtocolTest { request = new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1); - originResponse = make200Response(); + originResponse = HttpTestUtils.make200Response(); params = new CacheConfig(); params.setMaxCacheEntries(MAX_ENTRIES); @@ -67,19 +63,6 @@ public abstract class AbstractProtocolTest { EasyMock.verify(mockCache); } - protected HttpResponse make200Response() { - HttpResponse out = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - out.setHeader("Date", DateUtils.formatDate(new Date())); - out.setHeader("Server", "MockOrigin/1.0"); - out.setHeader("Content-Length", "128"); - out.setEntity(makeBody(128)); - return out; - } - - protected HttpEntity makeBody(int nbytes) { - return HttpTestUtils.makeBody(nbytes); - } - protected IExpectationSetters backendExpectsAnyRequest() throws Exception { HttpResponse resp = mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock .isA(HttpRequest.class), (HttpContext) EasyMock.isNull()); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/HttpTestUtils.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/HttpTestUtils.java index 12afb8e16..84f1a985b 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/HttpTestUtils.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/HttpTestUtils.java @@ -44,6 +44,7 @@ import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.BasicHeader; +import org.apache.http.message.BasicHttpResponse; import org.apache.http.message.BasicStatusLine; public class HttpTestUtils { @@ -288,4 +289,13 @@ public class HttpTestUtils { Date now = new Date(); return makeCacheEntry(now, now); } + + public static HttpResponse make200Response() { + HttpResponse out = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); + out.setHeader("Date", DateUtils.formatDate(new Date())); + out.setHeader("Server", "MockOrigin/1.0"); + out.setHeader("Content-Length", "128"); + out.setEntity(makeBody(128)); + return out; + } } \ No newline at end of file diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java index acd8108d8..d82c1de94 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java @@ -208,16 +208,10 @@ public class TestCacheInvalidator { } @Test - public void testInvalidatesRequestsWithClientCacheControlHeaders() throws Exception { + public void testDoesNotInvalidateRequestsWithClientCacheControlHeaders() throws Exception { HttpRequest request = new BasicHttpRequest("GET","/",HTTP_1_1); request.setHeader("Cache-Control","no-cache"); - final String theUri = "http://foo.example.com:80/"; - cacheReturnsEntryForUri(theUri); - Set variantURIs = new HashSet(); - cacheEntryHasVariantURIs(variantURIs); - - entryIsRemoved(theUri); replayMocks(); impl.flushInvalidatedCacheEntries(host, request); @@ -226,16 +220,10 @@ public class TestCacheInvalidator { } @Test - public void testInvalidatesRequestsWithClientPragmaHeaders() throws Exception { + public void testDoesNotInvalidateRequestsWithClientPragmaHeaders() throws Exception { HttpRequest request = new BasicHttpRequest("GET","/",HTTP_1_1); request.setHeader("Pragma","no-cache"); - final String theUri = "http://foo.example.com:80/"; - cacheReturnsEntryForUri(theUri); - Set variantURIs = new HashSet(); - cacheEntryHasVariantURIs(variantURIs); - - entryIsRemoved(theUri); replayMocks(); impl.flushInvalidatedCacheEntries(host, request); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java index 0911e4a1c..c918a0507 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; @@ -49,6 +50,7 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.impl.cookie.DateUtils; +import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHttpRequest; import org.apache.http.message.BasicHttpResponse; import org.apache.http.params.BasicHttpParams; @@ -99,6 +101,7 @@ public class TestCachingHttpClient { private HttpRequest request; private HttpContext context; private HttpParams params; + private HttpCacheEntry entry; @SuppressWarnings("unchecked") @Before @@ -128,6 +131,7 @@ public class TestCachingHttpClient { request = new BasicHttpRequest("GET", "/stuff", HttpVersion.HTTP_1_1); context = new BasicHttpContext(); params = new BasicHttpParams(); + entry = HttpTestUtils.makeCacheEntry(); impl = new CachingHttpClient( mockBackend, mockValidityPolicy, @@ -195,6 +199,8 @@ public class TestCachingHttpClient { responseProtocolValidationIsCalled(); + EasyMock.expect(mockCache.getCacheEntry(host, request)) + .andReturn(null); EasyMock.expect(mockCache.cacheAndReturnResponse(host, request, mockBackendResponse, requestDate, responseDate)) .andReturn(mockCachedResponse); @@ -206,6 +212,60 @@ public class TestCachingHttpClient { Assert.assertSame(mockCachedResponse, result); } + @Test + public void testOlderCacheableResponsesDoNotGoIntoCache() throws Exception { + responsePolicyAllowsCaching(true); + responseProtocolValidationIsCalled(); + + Date now = new Date(); + Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L); + Header entryDateHeader = new BasicHeader("Date", DateUtils.formatDate(now)); + Header[] headers = { entryDateHeader }; + entry = HttpTestUtils.makeCacheEntry(headers); + Header responseDateHeader = new BasicHeader("Date", DateUtils.formatDate(fiveSecondsAgo)); + + EasyMock.expect(mockCache.getCacheEntry(host, request)) + .andReturn(entry); + EasyMock.expect(mockBackendResponse.getFirstHeader("Date")) + .andReturn(responseDateHeader).anyTimes(); + + replayMocks(); + HttpResponse result = impl.handleBackendResponse(host, request, requestDate, + responseDate, mockBackendResponse); + verifyMocks(); + + Assert.assertSame(mockBackendResponse, result); + } + + @Test + public void testNewerCacheableResponsesReplaceExistingCacheEntry() throws Exception { + responsePolicyAllowsCaching(true); + responseProtocolValidationIsCalled(); + + Date now = new Date(); + Date fiveSecondsAgo = new Date(now.getTime() - 5 * 1000L); + Header entryDateHeader = new BasicHeader("Date", DateUtils.formatDate(fiveSecondsAgo)); + Header[] headers = { entryDateHeader }; + entry = HttpTestUtils.makeCacheEntry(headers); + Header responseDateHeader = new BasicHeader("Date", DateUtils.formatDate(now)); + + EasyMock.expect(mockCache.getCacheEntry(host, request)) + .andReturn(entry); + EasyMock.expect(mockBackendResponse.getFirstHeader("Date")) + .andReturn(responseDateHeader).anyTimes(); + EasyMock.expect(mockCache.cacheAndReturnResponse(host, request, + mockBackendResponse, requestDate, responseDate)) + .andReturn(mockCachedResponse); + + replayMocks(); + HttpResponse result = impl.handleBackendResponse(host, request, requestDate, + responseDate, mockBackendResponse); + verifyMocks(); + + Assert.assertSame(mockCachedResponse, result); + } + + @Test public void testRequestThatCannotBeServedFromCacheCausesBackendRequest() throws Exception { cacheInvalidatorWasCalled(); @@ -302,54 +362,139 @@ public class TestCachingHttpClient { } @Test - public void testRevalidationCallsHandleBackEndResponseWhenNot304() throws Exception { + public void testRevalidationCallsHandleBackEndResponseWhenNot200Or304() throws Exception { mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE); - conditionalRequestBuilderCalled(); + HttpRequest validate = + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpResponse originResponse = + new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_NOT_FOUND, "Not Found"); + HttpResponse finalResponse = HttpTestUtils.make200Response(); + + conditionalRequestBuilderReturns(validate); getCurrentDateReturns(requestDate); - backendCallWasMadeWithRequest(mockConditionalRequest); + backendCall(validate, originResponse); getCurrentDateReturns(responseDate); - backendResponseCodeIs(HttpStatus.SC_OK); - EasyMock.expect(mockCache.updateCacheEntry(host, request, - mockCacheEntry, mockBackendResponse, requestDate, responseDate)) - .andReturn(mockCachedResponse); + EasyMock.expect(impl.handleBackendResponse(host, validate, + requestDate, responseDate, originResponse)) + .andReturn(finalResponse); replayMocks(); - - HttpResponse result = impl.revalidateCacheEntry(host, request, context, - mockCacheEntry); - + HttpResponse result = + impl.revalidateCacheEntry(host, request, context, entry); verifyMocks(); - Assert.assertEquals(mockCachedResponse, result); - Assert.assertEquals(0, impl.getCacheMisses()); - Assert.assertEquals(0, impl.getCacheHits()); - Assert.assertEquals(1, impl.getCacheUpdates()); + Assert.assertSame(finalResponse, result); } @Test public void testRevalidationUpdatesCacheEntryAndPutsItToCacheWhen304ReturningCachedResponse() throws Exception { + mockImplMethods(GET_CURRENT_DATE); - conditionalRequestBuilderCalled(); + + HttpRequest validate = + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpResponse originResponse = + new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_NOT_MODIFIED, "Not Modified"); + HttpResponse finalResponse = HttpTestUtils.make200Response(); + + conditionalRequestBuilderReturns(validate); getCurrentDateReturns(requestDate); - backendCallWasMadeWithRequest(mockConditionalRequest); + backendCall(validate, originResponse); getCurrentDateReturns(responseDate); - backendResponseCodeIs(HttpStatus.SC_NOT_MODIFIED); EasyMock.expect(mockCache.updateCacheEntry(host, request, - mockCacheEntry, mockBackendResponse, requestDate, responseDate)) - .andReturn(mockCachedResponse); + entry, originResponse, requestDate, responseDate)) + .andReturn(finalResponse); replayMocks(); - - HttpResponse result = impl.revalidateCacheEntry(host, request, context, mockCacheEntry); - + HttpResponse result = + impl.revalidateCacheEntry(host, request, context, entry); verifyMocks(); - Assert.assertEquals(mockCachedResponse, result); - Assert.assertEquals(0, impl.getCacheMisses()); - Assert.assertEquals(0, impl.getCacheHits()); - Assert.assertEquals(1, impl.getCacheUpdates()); + Assert.assertSame(finalResponse, result); + } + + @Test + public void testRevalidationUpdatesCacheEntryAndPutsItToCacheWhen200ReturningCachedResponse() + throws Exception { + + mockImplMethods(GET_CURRENT_DATE); + + HttpRequest validate = + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpResponse originResponse = HttpTestUtils.make200Response(); + HttpResponse finalResponse = HttpTestUtils.make200Response(); + + conditionalRequestBuilderReturns(validate); + getCurrentDateReturns(requestDate); + backendCall(validate, originResponse); + getCurrentDateReturns(responseDate); + EasyMock.expect(mockCache.updateCacheEntry(host, request, + entry, originResponse, requestDate, responseDate)) + .andReturn(finalResponse); + + replayMocks(); + HttpResponse result = + impl.revalidateCacheEntry(host, request, context, entry); + verifyMocks(); + + Assert.assertSame(finalResponse, result); + } + + @Test + public void testRevalidationRetriesUnconditionallyIfOlderResponseReceived() + throws Exception { +// TODO + mockImplMethods(GET_CURRENT_DATE); + + Date now = new Date(); + Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L); + + Header[] headers = { + new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)), + new BasicHeader("Cache-Control","max-age=5"), + new BasicHeader("ETag", "\"etag1\"") + }; + entry = HttpTestUtils.makeCacheEntry(headers); + + HttpRequest validate = + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpResponse originResponse1 = + new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED, + "Not Modified"); + originResponse1.setHeader("Date", DateUtils.formatDate(elevenSecondsAgo)); + HttpRequest unconditional = + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpResponse originResponse2 = HttpTestUtils.make200Response(); + HttpResponse finalResponse = HttpTestUtils.make200Response(); + + conditionalRequestBuilderReturns(validate); + getCurrentDateReturns(requestDate); + backendCall(validate, originResponse1); + getCurrentDateReturns(responseDate); + EasyMock.expect(mockConditionalRequestBuilder.buildUnconditionalRequest(request, entry)) + .andReturn(unconditional); + final Date requestDate2 = new Date(); + getCurrentDateReturns(requestDate2); + backendCall(unconditional, originResponse2); + final Date responseDate2 = new Date(); + getCurrentDateReturns(responseDate2); + + EasyMock.expect(mockCache.updateCacheEntry(host, request, + entry, originResponse2, requestDate2, responseDate2)) + .andReturn(finalResponse); + + replayMocks(); + HttpResponse result = + impl.revalidateCacheEntry(host, request, context, entry); + verifyMocks(); + + Assert.assertSame(finalResponse, result); + } @Test @@ -1102,16 +1247,11 @@ public class TestCachingHttpClient { EasyMock.anyObject())).andReturn(b); } - private void backendResponseCodeIs(int code) { - EasyMock.expect(mockBackendResponse.getStatusLine()).andReturn(mockStatusLine); - EasyMock.expect(mockStatusLine.getStatusCode()).andReturn(code); - } - - private void conditionalRequestBuilderCalled() throws ProtocolException { - EasyMock.expect( - mockConditionalRequestBuilder.buildConditionalRequest( - EasyMock.anyObject(), - EasyMock.anyObject())).andReturn(mockConditionalRequest); + private void conditionalRequestBuilderReturns(HttpRequest validate) + throws Exception { + EasyMock.expect(mockConditionalRequestBuilder + .buildConditionalRequest(request, entry)) + .andReturn(validate); } private void getCurrentDateReturns(Date date) { @@ -1123,11 +1263,10 @@ public class TestCachingHttpClient { EasyMock.anyObject())).andReturn(allow); } - private void backendCallWasMadeWithRequest(HttpRequest request) throws IOException { - EasyMock.expect(mockBackend.execute( - EasyMock.anyObject(), - EasyMock.same(request), - EasyMock.anyObject())).andReturn(mockBackendResponse); + private void backendCall(HttpRequest req, HttpResponse resp) + throws Exception { + EasyMock.expect(mockBackend.execute(host, req, context)) + .andReturn(resp); } private void backendCallWasMade(HttpRequest request, HttpResponse response) throws IOException { diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestConditionalRequestBuilder.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestConditionalRequestBuilder.java index ae31f893a..a8fc280e6 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestConditionalRequestBuilder.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestConditionalRequestBuilder.java @@ -44,10 +44,14 @@ import org.junit.Test; public class TestConditionalRequestBuilder { private ConditionalRequestBuilder impl; + private HttpRequest request; + private HttpCacheEntry entry; @Before public void setUp() throws Exception { impl = new ConditionalRequestBuilder(); + request = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + entry = HttpTestUtils.makeCacheEntry(); } @Test @@ -170,4 +174,107 @@ public class TestConditionalRequestBuilder { } Assert.assertTrue(foundMaxAge0); } + + @Test + public void testBuildUnconditionalRequestUsesGETMethod() + throws Exception { + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + Assert.assertEquals("GET", result.getRequestLine().getMethod()); + } + + @Test + public void testBuildUnconditionalRequestUsesRequestUri() + throws Exception { + final String uri = "/theURI"; + request = new BasicHttpRequest("GET", uri, HttpVersion.HTTP_1_1); + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + Assert.assertEquals(uri, result.getRequestLine().getUri()); + } + + @Test + public void testBuildUnconditionalRequestUsesHTTP_1_1() + throws Exception { + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + Assert.assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion()); + } + + @Test + public void testBuildUnconditionalRequestAddsCacheControlNoCache() + throws Exception { + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + boolean ccNoCacheFound = false; + for(Header h : result.getHeaders("Cache-Control")) { + for(HeaderElement elt : h.getElements()) { + if ("no-cache".equals(elt.getName())) { + ccNoCacheFound = true; + } + } + } + Assert.assertTrue(ccNoCacheFound); + } + + @Test + public void testBuildUnconditionalRequestAddsPragmaNoCache() + throws Exception { + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + boolean ccNoCacheFound = false; + for(Header h : result.getHeaders("Pragma")) { + for(HeaderElement elt : h.getElements()) { + if ("no-cache".equals(elt.getName())) { + ccNoCacheFound = true; + } + } + } + Assert.assertTrue(ccNoCacheFound); + } + + @Test + public void testBuildUnconditionalRequestDoesNotUseIfRange() + throws Exception { + request.addHeader("If-Range","\"etag\""); + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + Assert.assertNull(result.getFirstHeader("If-Range")); + } + + @Test + public void testBuildUnconditionalRequestDoesNotUseIfMatch() + throws Exception { + request.addHeader("If-Match","\"etag\""); + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + Assert.assertNull(result.getFirstHeader("If-Match")); + } + + @Test + public void testBuildUnconditionalRequestDoesNotUseIfNoneMatch() + throws Exception { + request.addHeader("If-None-Match","\"etag\""); + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + Assert.assertNull(result.getFirstHeader("If-None-Match")); + } + + @Test + public void testBuildUnconditionalRequestDoesNotUseIfUnmodifiedSince() + throws Exception { + request.addHeader("If-Unmodified-Since", DateUtils.formatDate(new Date())); + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + Assert.assertNull(result.getFirstHeader("If-Unmodified-Since")); + } + + @Test + public void testBuildUnconditionalRequestDoesNotUseIfModifiedSince() + throws Exception { + request.addHeader("If-Modified-Since", DateUtils.formatDate(new Date())); + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + Assert.assertNull(result.getFirstHeader("If-Modified-Since")); + } + + @Test + public void testBuildUnconditionalRequestCarriesOtherRequestHeaders() + throws Exception { + request.addHeader("User-Agent","MyBrowser/1.0"); + HttpRequest result = impl.buildUnconditionalRequest(request, entry); + Assert.assertEquals("MyBrowser/1.0", + result.getFirstHeader("User-Agent").getValue()); + } + } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java index 41d0ab4e0..dc1f52c49 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java @@ -26,6 +26,7 @@ */ package org.apache.http.impl.client.cache; +import static org.easymock.classextension.EasyMock.*; import static org.junit.Assert.*; import java.io.IOException; @@ -33,12 +34,16 @@ import java.util.Date; import org.apache.http.Header; import org.apache.http.HeaderElement; +import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.BasicHttpRequest; +import org.apache.http.message.BasicHttpResponse; +import org.apache.http.protocol.HttpContext; +import org.easymock.Capture; import org.junit.Test; /* @@ -81,7 +86,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { */ private HttpRequest requestToPopulateStaleCacheEntry() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); @@ -218,7 +223,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { public void testReturnsCachedResponsesAppropriatelyWhenNoOriginCommunication() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); resp1.setHeader("Cache-Control", "public, max-age=5"); @@ -299,4 +304,131 @@ public class TestProtocolRecommendations extends AbstractProtocolTest { assertEquals(warning, result.getFirstHeader("Warning").getValue()); } + + /* + * "If an origin server wishes to force a semantically transparent cache + * to validate every request, it MAY assign an explicit expiration time + * in the past. This means that the response is always stale, and so the + * cache SHOULD validate it before using it for subsequent requests." + * + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.1 + */ + @Test + public void testRevalidatesCachedResponseWithExpirationInThePast() + throws Exception { + Date now = new Date(); + Date oneSecondAgo = new Date(now.getTime() - 1 * 1000L); + Date oneSecondFromNow = new Date(now.getTime() + 1 * 1000L); + Date twoSecondsFromNow = new Date(now.getTime() + 2 * 1000L); + HttpRequest req1 = + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpResponse resp1 = HttpTestUtils.make200Response(); + resp1.setHeader("ETag","\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(now)); + resp1.setHeader("Expires",DateUtils.formatDate(oneSecondAgo)); + + backendExpectsAnyRequest().andReturn(resp1); + + HttpRequest req2 = + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpRequest revalidate = + new BasicHttpRequest("GET", "/",HttpVersion.HTTP_1_1); + revalidate.setHeader("If-None-Match","\"etag\""); + + HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_NOT_MODIFIED, "Not Modified"); + resp2.setHeader("Date", DateUtils.formatDate(twoSecondsFromNow)); + resp2.setHeader("Expires", DateUtils.formatDate(oneSecondFromNow)); + resp2.setHeader("ETag","\"etag\""); + + expect(mockBackend.execute(isA(HttpHost.class), + eqRequest(revalidate), (HttpContext)isNull())) + .andReturn(resp2); + + replayMocks(); + impl.execute(host, req1); + HttpResponse result = impl.execute(host, req2); + verifyMocks(); + + assertEquals(HttpStatus.SC_OK, + result.getStatusLine().getStatusCode()); + } + + /* "When a client tries to revalidate a cache entry, and the response + * it receives contains a Date header that appears to be older than the + * one for the existing entry, then the client SHOULD repeat the + * request unconditionally, and include + * Cache-Control: max-age=0 + * to force any intermediate caches to validate their copies directly + * with the origin server, or + * Cache-Control: no-cache + * to force any intermediate caches to obtain a new copy from the + * origin server." + * + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.6 + */ + @Test + public void testRetriesValidationThatResultsInAnOlderDated304Response() + throws Exception { + Date now = new Date(); + Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); + Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L); + HttpRequest req1 = + new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpResponse resp1 = HttpTestUtils.make200Response(); + resp1.setHeader("ETag","\"etag\""); + resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); + resp1.setHeader("Cache-Control","max-age=5"); + + backendExpectsAnyRequest().andReturn(resp1); + + HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); + HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, + HttpStatus.SC_NOT_MODIFIED, "Not Modified"); + resp2.setHeader("ETag","\"etag\""); + resp2.setHeader("Date", DateUtils.formatDate(elevenSecondsAgo)); + + backendExpectsAnyRequest().andReturn(resp2); + + Capture cap = new Capture(); + HttpResponse resp3 = HttpTestUtils.make200Response(); + resp3.setHeader("ETag","\"etag2\""); + resp3.setHeader("Date", DateUtils.formatDate(now)); + resp3.setHeader("Cache-Control","max-age=5"); + + expect(mockBackend.execute(isA(HttpHost.class), capture(cap), + (HttpContext)isNull())) + .andReturn(resp3); + + replayMocks(); + impl.execute(host, req1); + impl.execute(host, req2); + verifyMocks(); + + HttpRequest captured = cap.getValue(); + boolean hasMaxAge0 = false; + boolean hasNoCache = false; + for(Header h : captured.getHeaders("Cache-Control")) { + for(HeaderElement elt : h.getElements()) { + if ("max-age".equals(elt.getName())) { + try { + int maxage = Integer.parseInt(elt.getValue()); + if (maxage == 0) { + hasMaxAge0 = true; + } + } catch (NumberFormatException nfe) { + // nop + } + } else if ("no-cache".equals(elt.getName())) { + hasNoCache = true; + } + } + } + assertTrue(hasMaxAge0 || hasNoCache); + assertNull(captured.getFirstHeader("If-None-Match")); + assertNull(captured.getFirstHeader("If-Modified-Since")); + assertNull(captured.getFirstHeader("If-Range")); + assertNull(captured.getFirstHeader("If-Match")); + assertNull(captured.getFirstHeader("If-Unmodified-Since")); + } } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java index ac7599966..9d8e3fbeb 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java @@ -866,21 +866,21 @@ public class TestProtocolRequirements extends AbstractProtocolTest { // put something cacheable in the cache HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.addHeader("Cache-Control", "max-age=3600"); resp1.setHeader(eHeader, oldVal); // get a head that penetrates the cache HttpRequest req2 = new BasicHttpRequest("HEAD", "/", HttpVersion.HTTP_1_1); req2.addHeader("Cache-Control", "no-cache"); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setEntity(null); resp2.setHeader(eHeader, newVal); // next request doesn't tolerate stale entry HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); req3.addHeader("Cache-Control", "max-stale=0"); - HttpResponse resp3 = make200Response(); + HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader(eHeader, newVal); EasyMock.expect( @@ -1136,7 +1136,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag\""); resp1.setHeader("Cache-Control", "max-age=3600"); @@ -1166,7 +1166,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag\""); resp1.setHeader("Cache-Control", "max-age=3600"); @@ -1198,7 +1198,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void test206ResponseGeneratedFromCacheMustHaveDateHeader() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag\""); resp1.setHeader("Cache-Control", "max-age=3600"); @@ -1307,7 +1307,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date nextSecond = new Date(now.getTime() + 1000L); Date inTwoHoursPlusASec = new Date(now.getTime() + 2 * 3600 * 1000L + 1000L); - HttpResponse originResponse2 = make200Response(); + HttpResponse originResponse2 = HttpTestUtils.make200Response(); originResponse2.setHeader("Date", DateUtils.formatDate(nextSecond)); originResponse2.setHeader("Cache-Control", "max-age=7200"); originResponse2.setHeader("Expires", DateUtils.formatDate(inTwoHoursPlusASec)); @@ -1351,7 +1351,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date oneHourAgo = new Date(now.getTime() - 3600 * 1000L); - originResponse = make200Response(); + originResponse = HttpTestUtils.make200Response(); originResponse.addHeader("Allow", "GET,HEAD"); originResponse.addHeader("Cache-Control", "max-age=3600"); originResponse.addHeader("Content-Language", "en"); @@ -1448,7 +1448,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("ETag", "\"etag1\""); byte[] bytes1 = new byte[128]; @@ -1476,7 +1476,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date inTwoSeconds = new Date(now.getTime() + 2000L); HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp3 = make200Response(); + HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Date", DateUtils.formatDate(inTwoSeconds)); resp3.setHeader("Cache-Control", "max-age=3600"); resp3.setHeader("ETag", "\"etag2\""); @@ -1524,7 +1524,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); Date oneHourAgo = new Date(now.getTime() - 3600L); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(oneHourAgo)); @@ -1553,7 +1553,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date inTwoSeconds = new Date(now.getTime() + 2000L); HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp3 = make200Response(); + HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Date", DateUtils.formatDate(inTwoSeconds)); resp3.setHeader("Cache-Control", "max-age=3600"); resp3.setHeader("ETag", "\"etag2\""); @@ -1812,7 +1812,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); req1.setHeader("Accept-Encoding", "gzip"); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"v1\""); resp1.setHeader("Cache-Control", "max-age=7200"); resp1.setHeader("Expires", DateUtils.formatDate(inTwoHours)); @@ -1823,7 +1823,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req1.setHeader("Accept-Encoding", "gzip"); req1.setHeader("Cache-Control", "no-cache"); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag", "\"v2\""); resp2.setHeader("Cache-Control", "max-age=3600"); resp2.setHeader("Expires", DateUtils.formatDate(inTwoHours)); @@ -1871,7 +1871,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "W/\"v1\""); resp1.setHeader("Allow", "GET,HEAD"); resp1.setHeader("Content-Encoding", "x-coding"); @@ -1920,7 +1920,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { // load cache with cacheable entry HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag1\""); resp1.setHeader("Cache-Control", "max-age=3600"); @@ -1942,7 +1942,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { // unconditional validation doesn't use If-None-Match HttpRequest unconditionalValidation = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); // new response to unconditional validation provides new body - HttpResponse resp3 = make200Response(); + HttpResponse resp3 = HttpTestUtils.make200Response(); resp1.setHeader("ETag", "\"etag2\""); resp1.setHeader("Cache-Control", "max-age=3600"); @@ -1980,7 +1980,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest initialRequest = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse cachedResponse = make200Response(); + HttpResponse cachedResponse = HttpTestUtils.make200Response(); cachedResponse.setHeader("Cache-Control", "max-age=3600"); cachedResponse.setHeader("ETag", "\"etag\""); @@ -2000,7 +2000,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { conditionalResponse.setHeader("X-Extra", "junk"); // to be used if the cache generates an unconditional validation - HttpResponse unconditionalResponse = make200Response(); + HttpResponse unconditionalResponse = HttpTestUtils.make200Response(); unconditionalResponse.setHeader("Date", DateUtils.formatDate(inFiveSeconds)); unconditionalResponse.setHeader("ETag", "\"etag\""); @@ -2373,7 +2373,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 25 * 1000L); HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("ETag", "\"etag\""); resp1.setHeader("Cache-Control", "max-age=5"); @@ -2438,7 +2438,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("ETag", "\"etag\""); resp1.setHeader("Cache-Control", "max-age=5"); @@ -2577,13 +2577,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1); - HttpResponse validated = make200Response(); + HttpResponse validated = HttpTestUtils.make200Response(); validated.setHeader("Cache-Control", "public"); validated.setHeader("Last-Modified", DateUtils.formatDate(oneYearAgo)); validated.setHeader("Content-Length", "128"); validated.setEntity(new ByteArrayEntity(bytes)); - HttpResponse reconstructed = make200Response(); + HttpResponse reconstructed = HttpTestUtils.make200Response(); Capture cap = new Capture(); @@ -2633,17 +2633,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest { // put an entry in the cache HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(inFiveSecond)); resp1.setHeader("ETag", "\"etag1\""); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Content-Length", "128"); - // force a revalidation + // force another origin hit HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - req2.setHeader("Cache-Control", "max-age=0,max-stale=0"); + req2.setHeader("Cache-Control", "no-cache"); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Date", DateUtils.formatDate(now)); // older resp2.setHeader("ETag", "\"etag2\""); resp2.setHeader("Cache-Control", "max-age=3600"); @@ -2761,7 +2761,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testSubrangeGETMustUseStrongComparisonForCachedResponse() throws Exception { Date now = new Date(); HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(now)); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("ETag", "\"etag\""); @@ -2801,7 +2801,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(now)); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); @@ -2871,7 +2871,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date twentySecondsAgo = new Date(now.getTime() - 20 * 1000L); HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(now)); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); @@ -2901,7 +2901,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(now)); resp1.setHeader("Cache-Control", "max-age=3600"); resp1.setHeader("Last-Modified", DateUtils.formatDate(tenSecondsAgo)); @@ -2988,7 +2988,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { * already present: - Content-Location - Content-MD5 - ETag - Last-Modified */ private void testDoesNotModifyHeaderFromOrigin(String header, String value) throws Exception { - originResponse = make200Response(); + originResponse = HttpTestUtils.make200Response(); originResponse.setHeader(header, value); backendExpectsAnyRequest().andReturn(originResponse); @@ -3061,7 +3061,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - originResponse = make200Response(); + originResponse = HttpTestUtils.make200Response(); originResponse.setHeader("Cache-Control", "max-age=3600"); originResponse.setHeader(header, value); @@ -3451,7 +3451,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ public void testCachedEntityBodyIsUsedForResponseAfter304Validation() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("ETag","\"etag\""); @@ -3509,7 +3509,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testResponseIncludesCacheEntryEndToEndHeadersForResponseAfter304Validation() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("ETag","\"etag\""); decorateWithEndToEndHeaders(resp1); @@ -3544,7 +3544,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testUpdatedEndToEndHeadersFrom304ArePassedOnResponseAndUpdatedInCacheEntry() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("ETag","\"etag\""); decorateWithEndToEndHeaders(resp1); @@ -3595,7 +3595,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testMultiHeadersAreSuccessfullyReplacedOn304Validation() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.addHeader("Cache-Control","max-age=3600"); resp1.addHeader("Cache-Control","public"); resp1.setHeader("ETag","\"etag\""); @@ -3654,7 +3654,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date twoSecondsAgo = new Date(now.getTime() - 2 * 1000L); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp1.setEntity(makeBody(50)); + resp1.setEntity(HttpTestUtils.makeBody(50)); resp1.setHeader("Server","MockServer/1.0"); resp1.setHeader("Date", DateUtils.formatDate(twoSecondsAgo)); resp1.setHeader("Cache-Control","max-age=3600"); @@ -3667,7 +3667,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp2.setEntity(makeBody(78)); + resp2.setEntity(HttpTestUtils.makeBody(78)); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Content-Range","bytes 50-127/128"); resp2.setHeader("Server","MockServer/1.0"); @@ -3678,7 +3678,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp3.setEntity(makeBody(128)); + resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); @@ -3703,7 +3703,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp1.setEntity(makeBody(50)); + resp1.setEntity(HttpTestUtils.makeBody(50)); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Content-Range","bytes 0-49/128"); resp1.setHeader("Server","MockServer/1.0"); @@ -3715,7 +3715,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp2.setEntity(makeBody(78)); + resp2.setEntity(HttpTestUtils.makeBody(78)); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Content-Range","bytes 50-127/128"); resp2.setHeader("ETag","\"etag1\""); @@ -3727,7 +3727,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp3.setEntity(makeBody(128)); + resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); @@ -3752,7 +3752,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp1.setEntity(makeBody(50)); + resp1.setEntity(HttpTestUtils.makeBody(50)); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Content-Range","bytes 0-49/128"); resp1.setHeader("ETag","\"etag1\""); @@ -3765,7 +3765,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp2.setEntity(makeBody(78)); + resp2.setEntity(HttpTestUtils.makeBody(78)); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Content-Range","bytes 50-127/128"); resp2.setHeader("ETag","\"etag2\""); @@ -3777,7 +3777,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp3.setEntity(makeBody(128)); + resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); @@ -3802,7 +3802,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp1.setEntity(makeBody(50)); + resp1.setEntity(HttpTestUtils.makeBody(50)); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Content-Range","bytes 0-49/128"); resp1.setHeader("ETag","\"etag1\""); @@ -3815,7 +3815,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp2.setEntity(makeBody(78)); + resp2.setEntity(HttpTestUtils.makeBody(78)); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Content-Range","bytes 50-127/128"); resp2.setHeader("Server","MockServer/1.0"); @@ -3827,7 +3827,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req3.setHeader("Range","bytes=0-49"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp3.setEntity(makeBody(128)); + resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); @@ -3853,7 +3853,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp1.setEntity(makeBody(50)); + resp1.setEntity(HttpTestUtils.makeBody(50)); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Content-Range","bytes 0-49/128"); resp1.setHeader("Server","MockServer/1.0"); @@ -3865,7 +3865,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp2.setEntity(makeBody(78)); + resp2.setEntity(HttpTestUtils.makeBody(78)); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Content-Range","bytes 50-127/128"); resp2.setHeader("ETag","\"etag1\""); @@ -3878,7 +3878,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req3.setHeader("Range","bytes=0-49"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp3.setEntity(makeBody(128)); + resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); @@ -3904,7 +3904,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp1.setEntity(makeBody(50)); + resp1.setEntity(HttpTestUtils.makeBody(50)); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Content-Range","bytes 0-49/128"); resp1.setHeader("Etag","\"etag1\""); @@ -3917,7 +3917,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp2.setEntity(makeBody(78)); + resp2.setEntity(HttpTestUtils.makeBody(78)); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Content-Range","bytes 50-127/128"); resp2.setHeader("ETag","\"etag2\""); @@ -3930,7 +3930,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req3.setHeader("Range","bytes=0-49"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp3.setEntity(makeBody(128)); + resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); @@ -3956,7 +3956,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp1.setEntity(makeBody(50)); + resp1.setEntity(HttpTestUtils.makeBody(50)); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Content-Range","bytes 0-49/128"); resp1.setHeader("Etag","\"etag1\""); @@ -3969,7 +3969,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp2.setEntity(makeBody(78)); + resp2.setEntity(HttpTestUtils.makeBody(78)); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Content-Range","bytes 50-127/128"); resp2.setHeader("ETag","\"etag2\""); @@ -3982,7 +3982,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req3.setHeader("Range","bytes=50-127"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp3.setEntity(makeBody(128)); + resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); @@ -4007,7 +4007,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req1.setHeader("Range","bytes=0-49"); HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp1.setEntity(makeBody(50)); + resp1.setEntity(HttpTestUtils.makeBody(50)); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Content-Range","bytes 0-49/128"); resp1.setHeader("Etag","\"etag1\""); @@ -4020,7 +4020,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req2.setHeader("Range","bytes=50-127"); HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"); - resp2.setEntity(makeBody(78)); + resp2.setEntity(HttpTestUtils.makeBody(78)); resp2.setHeader("Cache-Control","max-age=3600"); resp2.setHeader("Content-Range","bytes 50-127/128"); resp2.setHeader("ETag","\"etag2\""); @@ -4033,7 +4033,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { req3.setHeader("Range","bytes=0-49"); HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); - resp3.setEntity(makeBody(128)); + resp3.setEntity(HttpTestUtils.makeBody(128)); resp3.setHeader("Server","MockServer/1.0"); resp3.setHeader("Date", DateUtils.formatDate(now)); @@ -4063,7 +4063,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); req1.setHeader("Accept-Encoding","gzip"); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag1\""); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Vary","Accept-Encoding"); @@ -4073,7 +4073,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); req2.removeHeaders("Accept-Encoding"); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag","\"etag1\""); resp2.setHeader("Cache-Control","max-age=3600"); @@ -4096,7 +4096,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testCannotServeFromCacheForVaryStar() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag1\""); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Vary","*"); @@ -4105,7 +4105,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag","\"etag1\""); resp2.setHeader("Cache-Control","max-age=3600"); @@ -4147,7 +4147,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); req1.setHeader("User-Agent","MyBrowser/1.0"); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag1\""); resp1.setHeader("Cache-Control","max-age=3600"); resp1.setHeader("Vary","User-Agent"); @@ -4162,7 +4162,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { conditional.setHeader("User-Agent","MyBrowser/1.5"); conditional.setHeader("If-None-Match","\"etag1\""); - HttpResponse resp200 = make200Response(); + HttpResponse resp200 = HttpTestUtils.make200Response(); resp200.setHeader("ETag","\"etag1\""); resp200.setHeader("Vary","User-Agent"); @@ -4212,7 +4212,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { */ @Test public void testIncompleteResponseMustNotBeReturnedToClientWithoutMarkingItAs206() throws Exception { - originResponse.setEntity(makeBody(128)); + originResponse.setEntity(HttpTestUtils.makeBody(128)); originResponse.setHeader("Content-Length","256"); backendExpectsAnyRequest().andReturn(originResponse); @@ -4243,7 +4243,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { protected void testUnsafeOperationInvalidatesCacheForThatUri( HttpRequest unsafeReq) throws Exception, IOException { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public, max-age=3600"); backendExpectsAnyRequest().andReturn(resp1); @@ -4253,7 +4253,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(resp2); HttpRequest req3 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp3 = make200Response(); + HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Cache-Control","public, max-age=3600"); // this origin request MUST happen due to invalidation @@ -4287,7 +4287,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { protected void testUnsafeMethodInvalidatesCacheForHeaderUri( HttpRequest unsafeReq) throws Exception, IOException { HttpRequest req1 = new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public, max-age=3600"); backendExpectsAnyRequest().andReturn(resp1); @@ -4297,7 +4297,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(resp2); HttpRequest req3 = new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1); - HttpResponse resp3 = make200Response(); + HttpResponse resp3 = HttpTestUtils.make200Response(); resp3.setHeader("Cache-Control","public, max-age=3600"); // this origin request MUST happen due to invalidation @@ -4393,7 +4393,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpHost otherHost = new HttpHost("bar.example.com"); HttpRequest req1 = new BasicHttpRequest("GET", "/content", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public, max-age=3600"); backendExpectsAnyRequest().andReturn(resp1); @@ -4501,7 +4501,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testPOSTRequestsAreWrittenThroughToOrigin() throws Exception { HttpEntityEnclosingRequest req = new BasicHttpEntityEnclosingRequest("POST","/",HttpVersion.HTTP_1_1); - req.setEntity(makeBody(128)); + req.setEntity(HttpTestUtils.makeBody(128)); req.setHeader("Content-Length","128"); testRequestIsWrittenThroughToOrigin(req); } @@ -4510,7 +4510,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testPUTRequestsAreWrittenThroughToOrigin() throws Exception { HttpEntityEnclosingRequest req = new BasicHttpEntityEnclosingRequest("PUT","/",HttpVersion.HTTP_1_1); - req.setEntity(makeBody(128)); + req.setEntity(HttpTestUtils.makeBody(128)); req.setHeader("Content-Length","128"); testRequestIsWrittenThroughToOrigin(req); } @@ -4621,7 +4621,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(authorizedResponse); HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control","max-age=3600"); if (maxTimes > 0) { @@ -4640,7 +4640,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testSharedCacheMustNotNormallyCacheAuthorizedResponses() throws Exception { - HttpResponse resp = make200Response(); + HttpResponse resp = HttpTestUtils.make200Response(); resp.setHeader("Cache-Control","max-age=3600"); resp.setHeader("ETag","\"etag\""); testSharedCacheRevalidatesAuthorizedResponse(resp, 1, 1); @@ -4649,7 +4649,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testSharedCacheMayCacheAuthorizedResponsesWithSMaxAgeHeader() throws Exception { - HttpResponse resp = make200Response(); + HttpResponse resp = HttpTestUtils.make200Response(); resp.setHeader("Cache-Control","s-maxage=3600"); resp.setHeader("ETag","\"etag\""); testSharedCacheRevalidatesAuthorizedResponse(resp, 0, 1); @@ -4658,7 +4658,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testSharedCacheMustRevalidateAuthorizedResponsesWhenSMaxAgeIsZero() throws Exception { - HttpResponse resp = make200Response(); + HttpResponse resp = HttpTestUtils.make200Response(); resp.setHeader("Cache-Control","s-maxage=0"); resp.setHeader("ETag","\"etag\""); testSharedCacheRevalidatesAuthorizedResponse(resp, 1, 1); @@ -4667,7 +4667,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testSharedCacheMayCacheAuthorizedResponsesWithMustRevalidate() throws Exception { - HttpResponse resp = make200Response(); + HttpResponse resp = HttpTestUtils.make200Response(); resp.setHeader("Cache-Control","must-revalidate"); resp.setHeader("ETag","\"etag\""); testSharedCacheRevalidatesAuthorizedResponse(resp, 0, 1); @@ -4676,7 +4676,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testSharedCacheMayCacheAuthorizedResponsesWithCacheControlPublic() throws Exception { - HttpResponse resp = make200Response(); + HttpResponse resp = HttpTestUtils.make200Response(); resp.setHeader("Cache-Control","public"); testSharedCacheRevalidatesAuthorizedResponse(resp, 0, 1); } @@ -4696,7 +4696,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); req2.setHeader("Authorization",authorization2); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); Capture cap = new Capture(); EasyMock.expect(mockBackend.execute(EasyMock.eq(host), @@ -4720,7 +4720,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { throws Exception { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date",DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Cache-Control","s-maxage=5"); @@ -4733,7 +4733,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { throws Exception { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date",DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Cache-Control","maxage=5, must-revalidate"); @@ -4760,7 +4760,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(tenSecondsAgo)); resp1.setHeader("Cache-Control","max-age=5"); resp1.setHeader("Etag","\"etag\""); @@ -4769,7 +4769,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); req2.setHeader("Cache-Control","max-stale=60"); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); Capture cap = new Capture(); EasyMock.expect(mockBackend.execute(EasyMock.eq(host), @@ -4840,13 +4840,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { protected void testCacheIsNotUsedWhenRespondingToRequest(HttpRequest req) throws Exception { HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Etag","\"etag\""); resp1.setHeader("Cache-Control","max-age=3600"); backendExpectsAnyRequest().andReturn(resp1); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Etag","\"etag2\""); resp2.setHeader("Cache-Control","max-age=1200"); @@ -4899,7 +4899,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); req2.setHeader("Cache-Control","max-stale=3600"); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag","\"etag2\""); resp2.setHeader("Cache-Control","max-age=5, must-revalidate"); @@ -4931,7 +4931,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testStaleEntryWithMustRevalidateIsNotUsedWithoutRevalidatingWithOrigin() throws Exception { - HttpResponse response = make200Response(); + HttpResponse response = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); response.setHeader("Date",DateUtils.formatDate(tenSecondsAgo)); @@ -4968,7 +4968,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { @Test public void testGenerates504IfCannotRevalidateAMustRevalidateEntry() throws Exception { - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); resp1.setHeader("ETag","\"etag\""); @@ -4988,7 +4988,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testStaleEntryWithProxyRevalidateOnSharedCacheIsNotUsedWithoutRevalidatingWithOrigin() throws Exception { if (impl.isSharedCache()) { - HttpResponse response = make200Response(); + HttpResponse response = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); response.setHeader("Date",DateUtils.formatDate(tenSecondsAgo)); @@ -5003,7 +5003,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testGenerates504IfSharedCacheCannotRevalidateAProxyRevalidateEntry() throws Exception { if (impl.isSharedCache()) { - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); Date now = new Date(); Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); resp1.setHeader("ETag","\"etag\""); @@ -5025,13 +5025,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { throws Exception { if (impl.isSharedCache()) { HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","private,max-age=3600"); backendExpectsAnyRequest().andReturn(resp1); HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); // this backend request MUST happen backendExpectsAnyRequest().andReturn(resp2); @@ -5047,14 +5047,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { throws Exception { if (impl.isSharedCache()) { HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("X-Personal","stuff"); resp1.setHeader("Cache-Control","private=\"X-Personal\",s-maxage=3600"); backendExpectsAnyRequest().andReturn(resp1); HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); // this backend request MAY happen backendExpectsAnyRequest().andReturn(resp2).times(0,1); @@ -5079,14 +5079,14 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testNoCacheCannotSatisfyASubsequentRequestWithoutRevalidation() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Cache-Control","no-cache"); backendExpectsAnyRequest().andReturn(resp1); HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); // this MUST happen backendExpectsAnyRequest().andReturn(resp2); @@ -5101,7 +5101,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testNoCacheCannotSatisfyASubsequentRequestWithoutRevalidationEvenWithContraryIndications() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Cache-Control","no-cache,s-maxage=3600"); @@ -5109,7 +5109,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); req2.setHeader("Cache-Control","max-stale=7200"); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); // this MUST happen backendExpectsAnyRequest().andReturn(resp2); @@ -5130,7 +5130,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testNoCacheOnFieldIsNotReturnedWithoutRevalidation() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("X-Stuff","things"); resp1.setHeader("Cache-Control","no-cache=\"X-Stuff\", max-age=3600"); @@ -5138,7 +5138,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { backendExpectsAnyRequest().andReturn(resp1); HttpRequest req2 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("ETag","\"etag\""); resp2.setHeader("X-Stuff","things"); resp2.setHeader("Cache-Control","no-cache=\"X-Stuff\",max-age=3600"); @@ -5295,13 +5295,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testCacheDoesNotAssumeContentLocationHeaderIndicatesAnotherCacheableResource() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public,max-age=3600"); resp1.setHeader("Etag","\"etag\""); resp1.setHeader("Content-Location","http://foo.example.com/bar"); HttpRequest req2 = new BasicHttpRequest("GET", "/bar", HttpVersion.HTTP_1_1); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); resp2.setHeader("Cache-Control","public,max-age=3600"); resp2.setHeader("Etag","\"etag\""); @@ -5345,13 +5345,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { private void testInvalidExpiresHeaderIsTreatedAsStale( final String expiresHeader) throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public"); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Expires", expiresHeader); HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); backendExpectsAnyRequest().andReturn(resp1); // second request to origin MUST happen @@ -5384,13 +5384,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest { public void testExpiresHeaderEqualToDateHeaderIsTreatedAsStale() throws Exception { HttpRequest req1 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Cache-Control","public"); resp1.setHeader("ETag","\"etag\""); resp1.setHeader("Expires", resp1.getFirstHeader("Date").getValue()); HttpRequest req2 = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1); - HttpResponse resp2 = make200Response(); + HttpResponse resp2 = HttpTestUtils.make200Response(); backendExpectsAnyRequest().andReturn(resp1); // second request to origin MUST happen @@ -5692,7 +5692,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest { Date now = new Date(); Date twentySecondsAgo = new Date(now.getTime() - 20 * 1000L); - HttpResponse resp1 = make200Response(); + HttpResponse resp1 = HttpTestUtils.make200Response(); resp1.setHeader("Date", DateUtils.formatDate(twentySecondsAgo)); resp1.setHeader("Cache-Control","public,max-age=5"); resp1.setHeader("ETag", "\"etag1\""); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtcolRequirements.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtcolRequirements.java deleted file mode 100644 index e69de29bb..000000000 diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtocolRequirements.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtocolRequirements.java index e42cff959..7ac463d3e 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtocolRequirements.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/ehcache/TestEhcacheProtocolRequirements.java @@ -74,7 +74,7 @@ public class TestEhcacheProtocolRequirements extends TestProtocolRequirements{ request = new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1); - originResponse = make200Response(); + originResponse = HttpTestUtils.make200Response(); params = new CacheConfig(); params.setMaxObjectSizeBytes(MAX_BYTES);