public boolean hasCacheControlDirective(final HttpCacheEntry entry, final String directive) { final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elt = it.next(); if (directive.equalsIgnoreCase(elt.getName())) { return true; } } return false; }
boolean mayCallBackend(final HttpRequest request) { final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elt = it.next(); if ("only-if-cached".equals(elt.getName())) { log.debug("Request marked only-if-cached"); return false; } } return true; }
protected boolean hasCacheControlParameterFrom(final HttpMessage msg, final String[] params) { final Iterator<HeaderElement> it = MessageSupport.iterate(msg, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elem = it.next(); for (final String param : params) { if (param.equalsIgnoreCase(elem.getName())) { return true; } } } return false; }
private RequestProtocolError requestContainsNoCacheDirectiveWithFieldName(final HttpRequest request) { final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elt = it.next(); if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equalsIgnoreCase(elt.getName()) && elt.getValue() != null) { return RequestProtocolError.NO_CACHE_DIRECTIVE_WITH_FIELD_NAME; } } return null; } }
protected boolean isExplicitlyNonCacheable(final HttpResponse response) { final Iterator<HeaderElement> it = MessageSupport.iterate(response, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elem = it.next(); if (HeaderConstants.CACHE_CONTROL_NO_STORE.equals(elem.getName()) || HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elem.getName()) || (sharedCache && HeaderConstants.PRIVATE.equals(elem.getName()))) { return true; } } return false; }
private boolean from1_0Origin(final HttpResponse response) { final Iterator<HeaderElement> it = MessageSupport.iterate(response, HeaderConstants.VIA); while (it.hasNext()) { final HeaderElement elt = it.next(); final String proto = elt.toString().split("\\s")[0]; if (proto.contains("/")) { return proto.equals("HTTP/1.0"); } else { return proto.equals("1.0"); } } final ProtocolVersion version = response.getVersion() != null ? response.getVersion() : HttpVersion.DEFAULT; return HttpVersion.HTTP_1_0.equals(version); }
/** * Check entry against If-None-Match * @param request The current httpRequest being made * @param entry the cache entry * @return boolean does the etag validator match */ private boolean etagValidatorMatches(final HttpRequest request, final HttpCacheEntry entry) { final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG); final String etag = (etagHeader != null) ? etagHeader.getValue() : null; final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.IF_NONE_MATCH); while (it.hasNext()) { final HeaderElement elt = it.next(); final String reqEtag = elt.toString(); if (("*".equals(reqEtag) && etag != null) || reqEtag.equals(etag)) { return true; } } return false; }
private boolean mayReturnStaleIfError(final MessageHeaders headers, final String name, final long stalenessSecs) { boolean result = false; final Iterator<HeaderElement> it = MessageSupport.iterate(headers, name); while (it.hasNext()) { final HeaderElement elt = it.next(); if (HeaderConstants.STALE_IF_ERROR.equals(elt.getName())) { try { final int staleIfErrorSecs = Integer.parseInt(elt.getValue()); if (stalenessSecs <= staleIfErrorSecs) { result = true; break; } } catch (final NumberFormatException nfe) { // skip malformed directive } } } return result; }
protected long getMaxAge(final HttpCacheEntry entry) { long maxage = -1; final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elt = it.next(); if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName()) || "s-maxage".equals(elt.getName())) { try { final long currMaxAge = Long.parseLong(elt.getValue()); if (maxage == -1 || currMaxAge < maxage) { maxage = currMaxAge; } } catch (final NumberFormatException nfe) { // be conservative if can't parse maxage = 0; } } } return maxage; }
public boolean mayReturnStaleWhileRevalidating(final HttpCacheEntry entry, final Date now) { final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elt = it.next(); if (HeaderConstants.STALE_WHILE_REVALIDATE.equalsIgnoreCase(elt.getName())) { try { final int allowedStalenessLifetime = Integer.parseInt(elt.getValue()); if (getStalenessSecs(entry, now) <= allowedStalenessLifetime) { return true; } } catch (final NumberFormatException nfe) { // skip malformed directive } } } return false; }
private void stripOtherFreshnessDirectivesWithNoCache(final HttpRequest request) { final List<HeaderElement> outElts = new ArrayList<>(); boolean shouldStrip = false; final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elt = it.next(); if (!disallowedWithNoCache.contains(elt.getName())) { outElts.add(elt); } if (HeaderConstants.CACHE_CONTROL_NO_CACHE.equals(elt.getName())) { shouldStrip = true; } } if (!shouldStrip) { return; } request.removeHeaders(HeaderConstants.CACHE_CONTROL); request.setHeader(HeaderConstants.CACHE_CONTROL, buildHeaderFromElements(outElts)); }
boolean explicitFreshnessRequest(final HttpRequest request, final HttpCacheEntry entry, final Date now) { final Iterator<HeaderElement> it = MessageSupport.iterate(request, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elt = it.next(); if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) { try { final int maxstale = Integer.parseInt(elt.getValue()); final long age = validityPolicy.getCurrentAgeSecs(entry, now); final long lifetime = validityPolicy.getFreshnessLifetimeSecs(entry); if (age - lifetime > maxstale) { return true; } } catch (final NumberFormatException nfe) { return true; } } else if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName()) || HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) { return true; } } return false; }
public static final void assert110WarningFound(final HttpResponse response) { boolean found110Warning = false; final Iterator<HeaderElement> it = MessageSupport.iterate(response, HttpHeaders.WARNING); while (it.hasNext()) { final HeaderElement elt = it.next(); final String[] parts = elt.getName().split("\\s"); if ("110".equals(parts[0])) { found110Warning = true; break; } } Assert.assertTrue(found110Warning); }
@Test public void testBuildUnconditionalRequestAddsPragmaNoCache() throws Exception { final HttpRequest result = impl.buildUnconditionalRequest(request); boolean ccNoCacheFound = false; final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.PRAGMA); while (it.hasNext()) { final HeaderElement elt = it.next(); if ("no-cache".equals(elt.getName())) { ccNoCacheFound = true; } } Assert.assertTrue(ccNoCacheFound); }
@Test public void testBuildUnconditionalRequestAddsCacheControlNoCache() throws Exception { final HttpRequest result = impl.buildUnconditionalRequest(request); boolean ccNoCacheFound = false; final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elt = it.next(); if ("no-cache".equals(elt.getName())) { ccNoCacheFound = true; } } Assert.assertTrue(ccNoCacheFound); }
@Test public void testCacheEntryWithProxyRevalidateDoesEndToEndRevalidation() throws Exception { final HttpRequest basicRequest = new BasicHttpRequest("GET", "/"); final HttpRequest requestWrapper = RequestCopier.INSTANCE.copy(basicRequest); final Date now = new Date(); final Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L); final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); final Date nineSecondsAgo = new Date(now.getTime() - 9 * 1000L); final Header[] cacheEntryHeaders = new Header[] { new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)), new BasicHeader("ETag", "\"etag\""), new BasicHeader("Cache-Control","max-age=5, proxy-revalidate") }; final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(elevenSecondsAgo, nineSecondsAgo, cacheEntryHeaders); final HttpRequest result = impl.buildConditionalRequest(requestWrapper, cacheEntry); boolean foundMaxAge0 = false; final Iterator<HeaderElement> it = MessageSupport.iterate(result, HeaderConstants.CACHE_CONTROL); while (it.hasNext()) { final HeaderElement elt = it.next(); if ("max-age".equalsIgnoreCase(elt.getName()) && "0".equals(elt.getValue())) { foundMaxAge0 = true; } } Assert.assertTrue(foundMaxAge0); }
@Test public void testIdentityCodingIsNotUsedInContentEncodingHeader() throws Exception { originResponse.setHeader("Content-Encoding", "identity"); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); final ClassicHttpResponse result = execute(request); verifyMocks(); boolean foundIdentity = false; final Iterator<HeaderElement> it = MessageSupport.iterate(result, HttpHeaders.CONTENT_ENCODING); while (it.hasNext()) { final HeaderElement elt = it.next(); if ("identity".equalsIgnoreCase(elt.getName())) { foundIdentity = true; } } assertFalse(foundIdentity); }
@Test public void testMustNotAddMultipartByteRangeContentTypeTo416Response() throws Exception { originResponse = new BasicClassicHttpResponse(416, "Requested Range Not Satisfiable"); EasyMock.expect( mockExecChain.proceed( EasyMock.isA(ClassicHttpRequest.class), EasyMock.isA(ExecChain.Scope.class))).andReturn(originResponse); replayMocks(); final ClassicHttpResponse result = execute(request); verifyMocks(); if (result.getCode() == 416) { final Iterator<HeaderElement> it = MessageSupport.iterate(result, HttpHeaders.CONTENT_TYPE); while (it.hasNext()) { final HeaderElement elt = it.next(); Assert.assertFalse("multipart/byteranges".equalsIgnoreCase(elt.getName())); } } }
@Test public void testVaryStarIsNotGeneratedByProxy() throws Exception { request.setHeader("User-Agent","my-agent/1.0"); originResponse.setHeader("Cache-Control","public, max-age=3600"); originResponse.setHeader("Vary","User-Agent"); originResponse.setHeader("ETag","\"etag\""); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); final ClassicHttpResponse result = execute(request); verifyMocks(); final Iterator<HeaderElement> it = MessageSupport.iterate(result, HttpHeaders.VARY); while (it.hasNext()) { final HeaderElement elt = it.next(); Assert.assertFalse("*".equals(elt.getName())); } }
@Test public void testOrderOfMultipleTransferEncodingHeadersIsPreserved() throws Exception { originResponse.addHeader("Transfer-Encoding","chunked"); originResponse.addHeader("Transfer-Encoding","x-transfer"); backendExpectsAnyRequest().andReturn(originResponse); replayMocks(); final ClassicHttpResponse result = execute(request); verifyMocks(); int transfer_encodings = 0; final Iterator<HeaderElement> it = MessageSupport.iterate(result, HttpHeaders.TRANSFER_ENCODING); while (it.hasNext()) { final HeaderElement elt = it.next(); switch(transfer_encodings) { case 0: Assert.assertEquals("chunked",elt.getName()); break; case 1: Assert.assertEquals("x-transfer",elt.getName()); break; default: Assert.fail("too many transfer encodings"); } transfer_encodings++; } Assert.assertEquals(2, transfer_encodings); }