okhttp icon indicating copy to clipboard operation
okhttp copied to clipboard

Caching of 301 Responses

Open GokhanArik opened this issue 7 years ago • 7 comments

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

GokhanArik avatar Aug 30 '16 00:08 GokhanArik

OkHttp caches 301s. Could you provide an executable test case to demonstrate the problem?

swankjesse avatar Aug 30 '16 01:08 swankjesse

@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.

GokhanArik avatar Aug 30 '16 02:08 GokhanArik

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

swankjesse avatar Aug 30 '16 04:08 swankjesse

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 

GokhanArik avatar Aug 30 '16 06:08 GokhanArik

And here is the video of the behavior.

https://www.youtube.com/watch?v=ZMIzu-tuJGk

GokhanArik avatar Aug 30 '16 14:08 GokhanArik

No action for us to take on this. You might have to do your own response header rewriting to get caching to work.

swankjesse avatar Oct 16 '16 16:10 swankjesse

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.

yschimke avatar Oct 25 '21 19:10 yschimke