package com.apollographql.apollo.internal.cache.http; import java.io.IOException; import java.util.Date; import okhttp3.Protocol; import okhttp3.Request; import okhttp3.Response; import okhttp3.internal.Util; import okhttp3.internal.http.HttpDate; import okio.BufferedSink; import okio.BufferedSource; import okio.Okio; import okio.Sink; import okio.Source; import static com.apollographql.apollo.internal.cache.http.HttpCache.CACHE_EXPIRE_AFTER_READ_HEADER; import static com.apollographql.apollo.internal.cache.http.HttpCache.CACHE_EXPIRE_TIMEOUT_HEADER; import static com.apollographql.apollo.internal.cache.http.HttpCache.CACHE_FETCH_STRATEGY_HEADER; import static com.apollographql.apollo.internal.cache.http.HttpCache.CACHE_KEY_HEADER; import static com.apollographql.apollo.internal.cache.http.HttpCache.CACHE_PREFETCH_HEADER; import static com.apollographql.apollo.internal.cache.http.HttpCache.CACHE_SERVED_DATE_HEADER; final class Utils { static Response strip(Response response) { return response != null && response.body() != null ? response.newBuilder().body(null).networkResponse(null).cacheResponse(null).build() : response; } static Response withServedDateHeader(Response response) throws IOException { return response.newBuilder() .addHeader(CACHE_SERVED_DATE_HEADER, HttpDate.format(new Date())) .build(); } static boolean isPrefetchResponse(Request request) { return Boolean.TRUE.toString().equalsIgnoreCase(request.header(CACHE_PREFETCH_HEADER)); } static boolean shouldSkipCache(Request request) { String cacheKey = request.header(CACHE_KEY_HEADER); HttpCacheFetchStrategy fetchStrategy = fetchStrategy(request); return cacheKey == null || cacheKey.isEmpty() || fetchStrategy == null; } static boolean shouldSkipNetwork(Request request) { String cacheKey = request.header(CACHE_KEY_HEADER); HttpCacheFetchStrategy fetchStrategy = fetchStrategy(request); return cacheKey != null && !cacheKey.isEmpty() && fetchStrategy == HttpCacheFetchStrategy.CACHE_ONLY; } static boolean isNetworkOnly(Request request) { HttpCacheFetchStrategy fetchStrategy = fetchStrategy(request); return fetchStrategy == HttpCacheFetchStrategy.NETWORK_ONLY; } static boolean isNetworkFirst(Request request) { HttpCacheFetchStrategy fetchStrategy = fetchStrategy(request); return fetchStrategy == HttpCacheFetchStrategy.NETWORK_FIRST; } // static boolean shouldReturnStaleCache(Request request) { // String expireTimeoutHeader = request.header(HttpCache.CACHE_EXPIRE_TIMEOUT_HEADER); // return expireTimeoutHeader == null || expireTimeoutHeader.isEmpty(); // } static boolean shouldExpireAfterRead(Request request) { return Boolean.TRUE.toString().equalsIgnoreCase(request.header(CACHE_EXPIRE_AFTER_READ_HEADER)); } static Response unsatisfiableCacheRequest(Request request) { return new Response.Builder() .request(request) .protocol(Protocol.HTTP_1_1) .code(504) .message("Unsatisfiable Request (cache-only)") .body(Util.EMPTY_RESPONSE) .sentRequestAtMillis(-1L) .receivedResponseAtMillis(System.currentTimeMillis()) .build(); } static void copyResponseBody(Response response, Sink sink) throws IOException { final int bufferSize = 8 * 1024; BufferedSource responseBodySource = response.body().source(); BufferedSink cacheResponseBody = Okio.buffer(sink); while (responseBodySource.read(cacheResponseBody.buffer(), bufferSize) > 0) { cacheResponseBody.emit(); } closeQuietly(responseBodySource); } static void closeQuietly(Source source) { try { source.close(); } catch (Exception ignore) { // ignore } } static void closeQuietly(Response response) { try { if (response != null) { response.close(); } } catch (Exception ignore) { // ignore } } static boolean isStale(Request request, Response response) { String timeoutStr = request.header(CACHE_EXPIRE_TIMEOUT_HEADER); String servedDateStr = response.header(CACHE_SERVED_DATE_HEADER); if (servedDateStr == null || timeoutStr == null) { return true; } long timeout = Long.parseLong(timeoutStr); if (timeout == 0) { return false; } Date servedDate = HttpDate.parse(servedDateStr); long now = System.currentTimeMillis(); return servedDate == null || now - servedDate.getTime() > timeout; } private static HttpCacheFetchStrategy fetchStrategy(Request request) { String fetchStrategyHeader = request.header(CACHE_FETCH_STRATEGY_HEADER); if (fetchStrategyHeader == null || fetchStrategyHeader.isEmpty()) { return null; } for (HttpCacheFetchStrategy fetchStrategy : HttpCacheFetchStrategy.values()) { if (fetchStrategy.name().equals(fetchStrategyHeader)) { return fetchStrategy; } } return null; } private Utils() { } }