Search code examples
androidokhttpetagif-none-match

Okhttp doesn't return cached response when using Etags


I have a simple use case where a server returns an Etag for a request and that etag is added as a header (i.e. If-None-Match) to all subsequent url requests. The server can respond with a 200 if there is a change in the response or a 304 otherwise. For the latter, it makes sense to reuse the response from cache. But okhttp always returns null as the cached response.

I did some troubleshooting and the response is written to disk internally by okhttp but the CachingStrategy doesn't return it to the CacheInterceptor. Looking closely into the CachingStrategy class, there is documentation specifically stating that the cache won't be used:

 /**
     * Returns true if the request contains conditions that save the server from sending a response
     * that the client has locally. When a request is enqueued with its own conditions, the built-in
     * response cache won't be used.
     */
    private fun hasConditions(request: Request): Boolean =
        request.header("If-Modified-Since") != null || request.header("If-None-Match") != null
  }

Is there a way to workaround this behavior and use the cached response instead?

(I have caching enabled as described here and I am using okhttp version 3.10.0)

Also, strangely I am having to manually add the Etag. Okhttp fails to add the etag to subsequent requests on its own.

Edit - correction, Okhttp correctly adds the etag header. I needed to use a network interceptor vs a regular one to see the etag header being added to the subsequent requests

Somewhat related to these issues:


Solution

  • Either you do your own caching, or you let OkHttp’s cache do the caching. When you add your own conditions, OkHttp assumes you want full control of the caching and it does not participate in that.