I know there has been a lot of similar questions, but I have read them all and none of them really helped.
So, here is my problem:
I am using retrofit + okhttp to fetch some data from API and I'd like to cache them. Unfortunately, I don't have admin access to the API server so I can't modify headers returned by the server. (currently, server returns Cache-control: private)
So I decided to use okhttp header spoofing to insert appropriate cache headers. Sadly, no matter what I do, caching doesn't seem to work.
I initialise the api service like this:
int cacheSize = 10 * 1024 * 1024; // 10 MiB
File cacheFile = new File(context.getCacheDir(), "thumbs");
final Cache cache = new Cache(cacheFile, cacheSize);
OkHttpClient client = new OkHttpClient();
client.setCache(cache);
client.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.removeHeader("Access-Control-Allow-Origin")
.removeHeader("Vary")
.removeHeader("Age")
.removeHeader("Via")
.removeHeader("C3-Request")
.removeHeader("C3-Domain")
.removeHeader("C3-Date")
.removeHeader("C3-Hostname")
.removeHeader("C3-Cache-Control")
.removeHeader("X-Varnish-back")
.removeHeader("X-Varnish")
.removeHeader("X-Cache")
.removeHeader("X-Cache-Hit")
.removeHeader("X-Varnish-front")
.removeHeader("Connection")
.removeHeader("Accept-Ranges")
.removeHeader("Transfer-Encoding")
.header("Cache-Control", "public, max-age=60")
//.header("Expires", "Mon, 27 Apr 2015 08:15:14 GMT")
.build();
}
});
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_ROOT)
.setLogLevel(RestAdapter.LogLevel.HEADERS_AND_ARGS)
.setClient(new OkClient(client))
.setConverter(new SimpleXMLConverter(false))
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
if (Network.isConnected(context)) {
int maxAge = 60; // read from cache for 2 minutes
request.addHeader("Cache-Control", "public, max-age=" + maxAge);
} else {
int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
request.addHeader("Cache-Control",
"public, only-if-cached, max-stale=" + maxStale);
}
}
})
.build();
api = restAdapter.create(ApiService.class);
Of course, it's not necessary to remove all these headers, but I wanted to make the response as clean as possible to rule out some interference from these extra headers.
As you can see, I tried to also spoof Expires and Date header (I tried removing them, setting them so that there is exactly max-age differnece between them and also setting Expires far into future). I also experimented with various Cache-control values, but no luck.
I made sure the cacheFile exists, isDirectory and is writeable by the application.
These are the request and response headers as logged directly by retrofit:
Request:
Cache-Control: public, max-age=60
---> END HTTP (no body)
Response:
Date: Mon, 27 Apr 2015 08:41:10 GMT
Server: Apache/2.2.22 (Ubuntu)
Expires: Mon, 27 Apr 2015 08:46:10 GMT
Content-Type: text/xml; charset=UTF-8
OkHttp-Selected-Protocol: http/1.1
OkHttp-Sent-Millis: 1430124070000
OkHttp-Received-Millis: 1430124070040
Cache-Control: public, max-age=60
<--- END HTTP (-1-byte body)
<--- BODY: ...
And, finally one strange incident: At some point, the cache worked for a few minutes. I was getting reasonable hit counts, even offline requests returned cached values. (It happened while using the exact setting posted here) But when I restarted the app, everything was back to "normal" (constant hit count 0).
Co if anyone has any idea what could be the problem here, I'd be really glad for any help :)