/** Returns the source to satisfy {@code request} given this cached response. */ public ResponseSource chooseResponseSource(long nowMillis, RequestHeaders request) { /* * If this response shouldn't have been stored, it should never be used * as a response source. This check should be redundant as long as the * persistence store is well-behaved and the rules are constant. */ if (!isCacheable(request)) { return ResponseSource.NETWORK; } if (request.isNoCache() || request.hasConditions()) { return ResponseSource.NETWORK; } long ageMillis = computeAge(nowMillis); long freshMillis = computeFreshnessLifetime(); if (request.getMaxAgeSeconds() != -1) { freshMillis = Math.min(freshMillis, TimeUnit.SECONDS.toMillis(request.getMaxAgeSeconds())); } long minFreshMillis = 0; if (request.getMinFreshSeconds() != -1) { minFreshMillis = TimeUnit.SECONDS.toMillis(request.getMinFreshSeconds()); } long maxStaleMillis = 0; if (!mustRevalidate && request.getMaxStaleSeconds() != -1) { maxStaleMillis = TimeUnit.SECONDS.toMillis(request.getMaxStaleSeconds()); } if (!noCache && ageMillis + minFreshMillis < freshMillis + maxStaleMillis) { if (ageMillis + minFreshMillis >= freshMillis) { headers.add("Warning", "110 HttpURLConnection \"Response is stale\""); } /* * not available in API 8 if (ageMillis > TimeUnit.HOURS.toMillis(24) && isFreshnessLifetimeHeuristic()) { */ if (ageMillis > 24L * 60L * 60L * 1000L && isFreshnessLifetimeHeuristic()) { headers.add("Warning", "113 HttpURLConnection \"Heuristic expiration\""); } return ResponseSource.CACHE; } if (etag != null) { request.setIfNoneMatch(etag); } else if (lastModified != null) { request.setIfModifiedSince(lastModified); } else if (servedDate != null) { request.setIfModifiedSince(servedDate); } return request.hasConditions() ? ResponseSource.CONDITIONAL_CACHE : ResponseSource.NETWORK; }
/** Combines this cached header with a network header as defined by RFC 2616, 13.5.3. */ public ResponseHeaders combine(ResponseHeaders network) { RawHeaders result = new RawHeaders(); for (int i = 0; i < headers.length(); i++) { String fieldName = headers.getFieldName(i); String value = headers.getValue(i); if (fieldName.equals("Warning") && value.startsWith("1")) { continue; // drop 100-level freshness warnings } if (!isEndToEnd(fieldName) || network.headers.get(fieldName) == null) { result.add(fieldName, value); } } for (int i = 0; i < network.headers.length(); i++) { String fieldName = network.headers.getFieldName(i); if (isEndToEnd(fieldName)) { result.add(fieldName, network.headers.getValue(i)); } } return new ResponseHeaders(uri, result); }
public void setLocalTimestamps(long sentRequestMillis, long receivedResponseMillis) { this.sentRequestMillis = sentRequestMillis; headers.add(SENT_MILLIS, Long.toString(sentRequestMillis)); this.receivedResponseMillis = receivedResponseMillis; headers.add(RECEIVED_MILLIS, Long.toString(receivedResponseMillis)); }