okhttp
okhttp copied to clipboard
Caching of 301 Responses
Hi guys,
I'm using okhttp3 with Picasso and my images are not cached if they are accessed from redirected URIs.
It looks like Okhttp is caching initial call and redirect URI separately. When I turn off wifi and data, Okhttp
is looking for URL of the first call and comparing it with the request. get
method of Cache
class is where the cached data is being ignored.
Response response = entry.response(snapshot);
if (!entry.matches(request, response)) {
Util.closeQuietly(response.body());
return null;
}
I'm not sure if it is a bug or it is by design. If it is not bug, I would like to hear your advises to solve this problem.
Thanks
OkHttp caches 301s. Could you provide an executable test case to demonstrate the problem?
@swankjesse I created a sample project, I tried to keep it similar to code base I have in my project. Open the app, hit Download button when you are online. It will show the image. Kill the app, turn off data/wifi and then try it. It won't show the image. The image URL is not the one I'm using, this image is from FB but afaik it also returns 301.
https://github.com/GokhanArik/OkhttpCacheTest
EDIT
I just debugged this and FB's 302 is not cachable. I will update the URL and let you know. Anyway, the problem is not about caching. When I debug it, it passes through maybeCache
method, and it is cached. However, when I'm offline and make a call to get image, it searches the cache for the initial,failing 301 URL. Not the redirected one.
Yep. For me the Facebook image redirects with a 302. That redirect isn’t cached but the followup image is. You can hack a very dangerous, very bad interceptor to force a 301 and see that that caches completely.
https://gist.github.com/swankjesse/1d3ef753ae38d0fcea910cfa137b60a4
When I run your code I see that it is being cached. However, I still can't get it working in my project. I don't see the image when I'm offline. And I saw few people reporting the same issue before. I updated the URL if you want to check it again. This image doesn't prevent caching.
D/Picasso: Main created [R1] Request{https://frozen-shore-44150.herokuapp.com/image}
D/Picasso: Dispatcher enqueued [R1]+2ms
D/Picasso: Hunter executing [R1]+2ms
D/Picasso: Dispatcher retrying [R1]+522ms
D/Picasso: Hunter executing [R1]+524ms
D/Picasso: Dispatcher retrying [R1]+1070ms
D/Picasso: Hunter executing [R1]+1071ms
D/Picasso: Dispatcher batched [R1]+1087ms for error
D/Picasso: Main errored [R1]+1328ms
D/Picasso: Dispatcher delivered [R1]+1328ms
And here is the video of the behavior.
https://www.youtube.com/watch?v=ZMIzu-tuJGk
No action for us to take on this. You might have to do your own response header rewriting to get caching to work.
Temporarily reopening this to confirm the behaviour...
https://www.ryadel.com/en/clear-google-chrome-redirect-cache-for-single-url-page-howto/ https://datatracker.ietf.org/doc/html/rfc7234#section-4.2.2
My reading of this is the 301 can be cached even without any cache headers
Because of the requirements in Section 3, this means that, effectively, heuristics can only be used on responses without explicit freshness whose status codes are defined as cacheable by default (see Section 6.1 of [RFC7231])
However what I observe is that for a cacheable resource, served by a CDN but hidden behind 301 redirecting site URL, even with caching turned on I get two requests.
site url -> 301 (no cache headers) cdn url -> 304 (Last-Modified & ETag)
So for my client, I end up forcing very tolerant headers (max-age=604800,public). I was doing this for 200/image, but frustrated that I also need to guess for the 301.