HTTPCache { public HTTPResponse execute(final HTTPRequest request) { return execute(request, helper.isEndToEndReloadRequest(request)); } HTTPCache(CacheStorage storage, ResponseResolver resolver); void clear(); CacheStorage getStorage(); ResponseResolver getResolver(); CacheStatistics getStatistics(); HTTPResponse execute(final HTTPRequest request); HTTPResponse executeRefresh(final HTTPRequest request); void shutdown(); boolean isTranslateHEADToGET(); void setTranslateHEADToGET(boolean translateHEADToGET);  }
@Test public void testResponseWherePayloadHasBeenRemoved() throws IOException { HTTPRequest request = new HTTPRequest(DUMMY_URI); Payload payload = mock(Payload.class); when(payload.isAvailable()).thenReturn(false); CacheItem item = new DefaultCacheItem(new HTTPResponse(Optional.of(payload), Status.OK, new Headers())); assertTrue("The cached item was not stale", item.isStale(LocalDateTime.now())); when(cacheStorage.get(request)).thenReturn(item); HTTPResponse resolvedResponse = new HTTPResponse(createClosedPayload(), Status.OK, new Headers()); when(responseResolver.resolve(isA(HTTPRequest.class))).thenReturn(resolvedResponse); when(cacheStorage.insert(isA(HTTPRequest.class), eq(resolvedResponse))).thenReturn(resolvedResponse); HTTPResponse response = cache.execute(request); assertTrue("None match was not empty", request.getHeaders().getConditionals().getNoneMatch().isEmpty()); verify(responseResolver, atLeast(1)).resolve(isA(HTTPRequest.class)); assertTrue("response did not have payload", response.hasPayload()); assertTrue(response.getPayload().get().isAvailable()); }
@Test public void testConditionalRequestWhereResponsePayloadHasBeenRemoved() throws IOException { HTTPRequest request = new HTTPRequest(DUMMY_URI); Headers headers = new Headers(); headers = headers.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, LocalDateTime.now())); headers = headers.add(HeaderConstants.ETAG, new Tag("foo", false).format()); headers = headers.add(HeaderConstants.CACHE_CONTROL, "max-age=10"); Payload payload = mock(Payload.class); when(payload.isAvailable()).thenReturn(false); CacheItem item = new DefaultCacheItem(new HTTPResponse(Optional.of(payload), Status.OK, headers)); when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(item); final HTTPResponse resolvedResponse = new HTTPResponse(createClosedPayload(), Status.OK, headers); when(responseResolver.resolve(isA(HTTPRequest.class))).thenReturn(resolvedResponse); when(cacheStorage.insert(isA(HTTPRequest.class), eq(resolvedResponse))).thenReturn(resolvedResponse); HTTPResponse response = cache.execute(request); assertTrue("None match was not empty", request.getHeaders().getConditionals().getNoneMatch().isEmpty()); verify(responseResolver, atLeast(1)).resolve(isA(HTTPRequest.class)); verify(cacheStorage, times(1)).insert(isA(HTTPRequest.class), eq(resolvedResponse)); assertTrue("Response did not have a payload", response.hasPayload()); assertTrue("Payload was not available", response.getPayload().get().isAvailable()); }
@Test public void testExternalConditionalRequestWhereResponsePayloadHasBeenRemoved() throws IOException { HTTPRequest request = new HTTPRequest(DUMMY_URI); Tag tag = new Tag("foo", false); request = request.addIfNoneMatch(tag); Headers headers = new Headers(); headers = headers.add(HeaderConstants.ETAG, tag.format()); headers = headers.add(HeaderConstants.CACHE_CONTROL, "max-age=10"); Payload payload = mock(Payload.class); when(payload.isAvailable()).thenReturn(false); when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(new DefaultCacheItem(new HTTPResponse(Optional.of(payload), Status.OK, headers))); HTTPResponse resolvedResponse = new HTTPResponse(createClosedPayload(), Status.OK, new Headers()); when(responseResolver.resolve(isA(HTTPRequest.class))).thenReturn(resolvedResponse); when(cacheStorage.insert(isA(HTTPRequest.class), eq(resolvedResponse))).thenReturn(resolvedResponse); HTTPResponse response = cache.execute(request); verify(responseResolver, atLeast(1)).resolve(isA(HTTPRequest.class)); assertTrue(response.hasPayload()); assertTrue(response.getPayload().get().isAvailable()); }
@Test public void testConditionalGet() throws IOException { HTTPRequest request = new HTTPRequest(URI.create("foo")); LocalDateTime prev = LocalDateTime.now(); Headers responseHeaders = new Headers(); responseHeaders = responseHeaders.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, prev)); responseHeaders = responseHeaders.add(new Header(HeaderConstants.CACHE_CONTROL, "private, max-age=60")); responseHeaders = responseHeaders.add(new Header(HeaderConstants.ETAG, "\"1234\"")); when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(new DefaultCacheItem(new HTTPResponse(createClosedPayload(), Status.OK, responseHeaders))); Headers updatedHeaders = new Headers(responseHeaders); updatedHeaders = updatedHeaders.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, prev.plusMinutes(2))); when(responseResolver.resolve(isA(HTTPRequest.class))).thenReturn(new HTTPResponse(Status.NOT_MODIFIED, updatedHeaders)); HTTPResponse response = cache.execute(request); Assert.assertNotNull("Response was null", response); Assert.assertTrue("The payload was null", response.getPayload().isPresent()); Assert.assertNotNull("The payload had a null inputstream", response.getPayload().get().getInputStream()); }
@Test public void testExternalConditionalGet() throws IOException { HTTPRequest request = new HTTPRequest(URI.create("foo")); request = request.addIfNoneMatch(new Tag("1234")); Headers responseHeaders = new Headers(); responseHeaders = responseHeaders.add(new Header(HeaderConstants.CACHE_CONTROL, "private, max-age=60")); responseHeaders = responseHeaders.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, LocalDateTime.now())); responseHeaders = responseHeaders.add(new Header(HeaderConstants.ETAG, "\"1234\"")); when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(new DefaultCacheItem(new HTTPResponse(createClosedPayload(), Status.OK, responseHeaders))); HTTPResponse response = cache.execute(request); Assert.assertNotNull("Response was null", response); Assert.assertFalse("The payload was not null", response.getPayload().isPresent()); Assert.assertEquals("Wrong status", Status.NOT_MODIFIED, response.getStatus()); }
@Test public void testConditionalGetWithLastModified() throws IOException { HTTPRequest request = new HTTPRequest(URI.create("foo")); Headers responseHeaders = new Headers(); responseHeaders = responseHeaders.add(new Header(HeaderConstants.CACHE_CONTROL, "private, max-age=60")); LocalDateTime dateHeader = LocalDateTime.now(); responseHeaders = responseHeaders.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, dateHeader)); responseHeaders = responseHeaders.add(HeaderUtils.toHttpDate(HeaderConstants.LAST_MODIFIED, dateHeader.minusSeconds(2))); when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(new DefaultCacheItem(new HTTPResponse(createClosedPayload(), Status.OK, responseHeaders))); Headers updatedHeaders = new Headers(responseHeaders); updatedHeaders = updatedHeaders.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, dateHeader.plusMinutes(2))); when(responseResolver.resolve(isA(HTTPRequest.class))).thenReturn(new HTTPResponse(Status.NOT_MODIFIED, updatedHeaders)); HTTPResponse response = cache.execute(request); Assert.assertNotNull("Response was null", response); Assert.assertTrue("The payload was null", response.getPayload().isPresent()); Assert.assertEquals("Wrong status", Status.OK, response.getStatus()); }
@Test public void testExternalConditionalGetWithLastModified() throws IOException { LocalDateTime dateHeader = LocalDateTime.now(); LocalDateTime lastModified = dateHeader.minusSeconds(2); HTTPRequest request = new HTTPRequest(URI.create("foo")); request = request.withIfModifiedSince(lastModified); Headers responseHeaders = new Headers(); responseHeaders = responseHeaders.add(new Header(HeaderConstants.CACHE_CONTROL, "private, max-age=60")); responseHeaders = responseHeaders.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, dateHeader)); responseHeaders = responseHeaders.add(HeaderUtils.toHttpDate(HeaderConstants.LAST_MODIFIED, lastModified)); when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(new DefaultCacheItem(new HTTPResponse(createClosedPayload(), Status.OK, responseHeaders))); HTTPResponse response = cache.execute(request); Assert.assertNotNull("Response was null", response); Assert.assertFalse("The payload was not null", response.hasPayload()); Assert.assertEquals("Wrong status", Status.NOT_MODIFIED, response.getStatus()); }
@Test public void testExternalConditionalGetWitchDoesNotMatch() throws IOException { HTTPRequest request = new HTTPRequest(URI.create("foo")); request = request.addIfNoneMatch(new Tag("12345")); Headers responseHeaders = new Headers(); responseHeaders = responseHeaders.add(new Header(HeaderConstants.CACHE_CONTROL, "private, max-age=60")); responseHeaders = responseHeaders.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, LocalDateTime.now())); responseHeaders = responseHeaders.add(new Header(HeaderConstants.ETAG, "\"1234\"")); when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(new DefaultCacheItem(new HTTPResponse(createClosedPayload(), Status.OK, responseHeaders))); HTTPResponse response = cache.execute(request); Assert.assertNotNull("Response was null", response); Assert.assertTrue("The payload was null", response.hasPayload()); Assert.assertEquals("Wrong status", Status.OK, response.getStatus()); }
@Test public void testUnconditionalGET() throws IOException { HTTPRequest request = new HTTPRequest(REQUEST_URI); request = request.addIfNoneMatch(Tag.ALL); Headers responseHeaders = new Headers(); responseHeaders = responseHeaders.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, LocalDateTime.now())); responseHeaders = responseHeaders.add(new Header(HeaderConstants.CACHE_CONTROL, "private, max-age=60")); responseHeaders = responseHeaders.add(new Header(HeaderConstants.ETAG, "\"1234\"")); HTTPResponse resolvedResponse = new HTTPResponse(createClosedPayload(), Status.OK, responseHeaders); when(responseResolver.resolve(request)).thenReturn(resolvedResponse); when(cacheStorage.insert(eq(request), eq(resolvedResponse))).thenReturn(resolvedResponse); HTTPResponse response = cache.execute(request); verify(cacheStorage, times(1)).insert(eq(request), eq(resolvedResponse)); Assert.assertNotNull("Response was null", response); Assert.assertEquals("Wrong status", Status.OK, response.getStatus()); Assert.assertTrue("The payload was null", response.hasPayload()); }
@Test public void testEndToEndReload() throws IOException { String initialETagVal = "\"1\""; String updatedETagVal = "\"2\""; HTTPRequest request = new HTTPRequest(REQUEST_URI).addHeader(HeaderConstants.CACHE_CONTROL, "no-cache"); Headers initialResponseHeaders = new Headers(); initialResponseHeaders = initialResponseHeaders.add(new Header(HeaderConstants.ETAG, initialETagVal)); initialResponseHeaders = initialResponseHeaders.add(new Header(HeaderConstants.CACHE_CONTROL, "private, max-age=60")); HTTPResponse initialResponse = new HTTPResponse(createClosedPayload(), Status.OK, initialResponseHeaders); Headers updatedResponseHeaders = new Headers(); updatedResponseHeaders = updatedResponseHeaders.add(new Header(HeaderConstants.ETAG, updatedETagVal)); HTTPResponse updatedResponse = new HTTPResponse(createClosedPayload(), Status.OK, updatedResponseHeaders); when(cacheStorage.insert(eq(request), eq(initialResponse))).thenReturn(initialResponse); when(cacheStorage.insert(eq(request), eq(updatedResponse))).thenReturn(updatedResponse); when(cacheStorage.get(request)).thenReturn(new DefaultCacheItem(initialResponse)); when(responseResolver.resolve(isA(HTTPRequest.class))).thenReturn(updatedResponse); HTTPResponse response = cache.execute(request); Assert.assertEquals("Wrong status", Status.OK, response.getStatus()); Assert.assertFalse("Got the cached response instead of the updated one.", Tag.parse(initialETagVal).equals(response.getHeaders().getETag())); Assert.assertEquals("Did not get the updated response (ETag does not match)", Tag.parse(updatedETagVal), response.getHeaders().getETag()); }
@Test public void testCacheResponseWithInvalidationPUT() { Headers responseHeaders = new Headers(); responseHeaders.add(new Header(HeaderConstants.CACHE_CONTROL, "private, max-age=60")); doGet(responseHeaders, Status.OK, 1); HTTPRequest request = new HTTPRequest(REQUEST_URI, HTTPMethod.PUT); cache.execute(request); when(cacheStorage.size()).thenReturn(0); assertEquals(0, cacheStorage.size()); }
@Test public void testPOST() throws IOException { HTTPRequest request = new HTTPRequest(REQUEST_URI, HTTPMethod.POST); when(responseResolver.resolve(isA(HTTPRequest.class))).thenReturn(new HTTPResponse(Status.CREATED, new Headers())); cache.execute(request); when(cacheStorage.size()).thenReturn(0); assertEquals(0, cacheStorage.size()); }
@Test public void testTRACE() throws IOException { HTTPRequest request = new HTTPRequest(REQUEST_URI, HTTPMethod.TRACE); when(responseResolver.resolve(isA(HTTPRequest.class))).thenReturn(new HTTPResponse(Status.CREATED, new Headers())); cache.execute(request); when(cacheStorage.size()).thenReturn(0); assertEquals(0, cacheStorage.size()); }
@Test public void testGetANDTRACE() { doGet(new Headers(), Status.OK, 1); HTTPRequest request = new HTTPRequest(REQUEST_URI, HTTPMethod.TRACE); cache.execute(request); when(cacheStorage.size()).thenReturn(1); assertEquals(1, cacheStorage.size()); }
@Test public void testHEADAndGET() throws IOException { HTTPRequest request = new HTTPRequest(REQUEST_URI, HTTPMethod.HEAD); when(responseResolver.resolve(isA(HTTPRequest.class))).thenReturn(new HTTPResponse(Status.OK, new Headers())); HTTPResponse response = cache.execute(request); assertFalse(response.hasPayload()); assertEquals(0, request.getHeaders().size()); when(cacheStorage.size()).thenReturn(1); assertEquals(1, cacheStorage.size()); response = doGet(new Headers(), Status.OK, 1); assertTrue("No payload on get", response.hasPayload()); when(cacheStorage.size()).thenReturn(1); assertEquals(1, cacheStorage.size()); }
@Test public void testHEADWithETagAndGETWithItemInCache() throws IOException { HTTPRequest request = new HTTPRequest(REQUEST_URI, HTTPMethod.HEAD); Headers headers = new Headers(); headers = headers.add(new Header("ETag", "\"foo\"")); headers = headers.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, LocalDateTime.now())); HTTPResponse cachedResponse = new HTTPResponse(createClosedPayload(), Status.OK, headers); when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(new DefaultCacheItem(cachedResponse) { @Override public boolean isStale(LocalDateTime requestTime) { return false; } }); HTTPResponse response = cache.execute(request); assertEquals("Conditionals was set, incorrect", 0, request.getHeaders().getConditionals().toHeaders().size()); assertFalse(response.hasPayload()); response = doGet(new Headers(), Status.OK, 1); assertTrue("No payload on get", response.hasPayload()); when(cacheStorage.size()).thenReturn(1); assertEquals(1, cacheStorage.size()); }
@Test public void testCacheNoneStaleRequestRegression() throws IOException { HTTPRequest request = new HTTPRequest(REQUEST_URI, HTTPMethod.HEAD); Headers headers = new Headers(); headers = headers.add(new Header("Cache-Control", "private, max-age=65000")); headers = headers.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, LocalDateTime.now())); HTTPResponse cachedResponse = new HTTPResponse(createClosedPayload(), Status.OK, headers); CacheItem item = new DefaultCacheItem(cachedResponse); when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(item); assertFalse(item.isStale(LocalDateTime.now())); HTTPResponse response = cache.execute(request); assertFalse(response.getPayload().isPresent()); verify(responseResolver, never()).resolve(request); }
@Test public void testCacheWithRequestAllowingStaleReponse() throws IOException { LocalDateTime now = LocalDateTime.of(2010, 2, 3, 10, 0, 0, 0); Headers headers = new Headers(); headers = headers.add(new Header("Cache-Control", "private, max-age=5")); headers = headers.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, now)); HTTPResponse cachedResponse = new HTTPResponse(Status.OK, headers); CacheItem item = new DefaultCacheItem(cachedResponse, now); now = LocalDateTime.of(2010, 2, 3, 10, 0, 10, 0); HTTPRequest request = new HTTPRequest(REQUEST_URI).headers(new Headers().add(HeaderConstants.CACHE_CONTROL, "max-stale=10")); when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(item); assertTrue("Item was not stale", item.isStale(now)); HTTPResponse response = cache.execute(request); verify(responseResolver, never()).resolve(request); assertTrue("No warn header", response.getHeaders().contains("warning")); }
@Test public void makeSureHEADRequestInvalidatesCacheIfNot304() throws Exception { LocalDateTime base = LocalDateTime.of(2010, 2, 3, 10, 0, 0, 0); Headers headers = new Headers(); headers = headers.add(new CacheControl.Builder().maxAge(50).withPrivate().build().toHeader()); headers = headers.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, base)); HTTPResponse cachedResponse = new HTTPResponse(createClosedPayload(), Status.OK, headers); CacheItem item = new DefaultCacheItem(cachedResponse) { @Override public boolean isStale(LocalDateTime requestTime) { return true; } }; when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(item); HTTPRequest request = new HTTPRequest(REQUEST_URI, HTTPMethod.HEAD); base = base.plusHours(1); when(responseResolver.resolve(request)).thenReturn(new HTTPResponse(Status.NOT_FOUND, new Headers().withDate(base))); HTTPResponse response = cache.execute(request); verify(cacheStorage, atLeastOnce()).invalidate(REQUEST_URI); assertFalse(response.getPayload().isPresent()); }
@Test public void makeSureHEADRequestUpdatesCacheI304() throws Exception { LocalDateTime base = LocalDateTime.of(2010, 2, 3, 10, 0, 0, 0); Headers headers = new Headers(); CacheControl cacheControl = new CacheControl.Builder().maxAge(50).withPrivate().build(); headers = headers.add(cacheControl.toHeader()); headers = headers.add(HeaderUtils.toHttpDate(HeaderConstants.DATE, base)); headers = headers.withETag(new Tag("foo")); HTTPResponse cachedResponse = new HTTPResponse(createClosedPayload(), Status.OK, headers); CacheItem item = new DefaultCacheItem(cachedResponse) { @Override public boolean isStale(LocalDateTime requestTime) { return true; } }; when(cacheStorage.get(isA(HTTPRequest.class))).thenReturn(item); HTTPRequest request = new HTTPRequest(REQUEST_URI, HTTPMethod.HEAD); base = base.plusHours(1); HTTPResponse HEADResponse = new HTTPResponse(Status.NOT_MODIFIED, new Headers().withDate(base).withCacheControl(cacheControl)); when(responseResolver.resolve(request)).thenReturn(HEADResponse); when(cacheStorage.update(isA(HTTPRequest.class), isA(HTTPResponse.class))).thenReturn(new HTTPResponse(createClosedPayload(), Status.OK, HEADResponse.getHeaders())); HTTPResponse response = cache.execute(request); verify(cacheStorage, never()).invalidate(REQUEST_URI); verify(cacheStorage, atLeastOnce()).update(isA(HTTPRequest.class), isA(HTTPResponse.class)); assertFalse(response.hasPayload()); }
@Test public void testNeitherContentLocationNorLocationInvalidatedIfHostNotSameAsRequest() throws IOException { URI requestUri = URI.create("http: URI contentLocationUri = URI.create("http: URI locationUri = URI.create("http: HTTPRequest request = new HTTPRequest(requestUri, HTTPMethod.POST); Headers responseHeaders = new Headers(). add(new Header(HeaderConstants.CONTENT_LOCATION, contentLocationUri.toString())). add(new Header(HeaderConstants.LOCATION, locationUri.toString())); when(responseResolver.resolve(isA(HTTPRequest.class))).thenReturn(new HTTPResponse(Status.CREATED, responseHeaders)); cache.execute(request); verify(cacheStorage, never()).invalidate(contentLocationUri); verify(cacheStorage, never()).invalidate(locationUri); }