Je sais qu'il y a eu beaucoup de questions similaires, mais je les ai toutes lues et aucune d'elles n'a vraiment aidé.Retrofit + OkHTTP - le cache de réponse ne fonctionne pas
Donc, voici mon problème:
J'utilise retrofit + okhttp pour récupérer des données de l'API et je voudrais les mettre en cache. Malheureusement, je n'ai pas d'accès admin au serveur API, donc je ne peux pas modifier les en-têtes renvoyés par le serveur. (actuellement, le serveur retourne Cache-control: private)
J'ai donc décidé d'utiliser la falsification d'en-tête okhttp pour insérer des en-têtes de cache appropriés. Malheureusement, peu importe ce que je fais, la mise en cache ne semble pas fonctionner.
J'Initialise le service api comme ceci:
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);
Bien sûr, il n'est pas nécessaire d'enlever tous ces en-têtes, mais je voulais faire la réponse aussi propre que possible pour écarter des interférences de ces supplémentaires en-têtes. Comme vous pouvez le voir, j'ai aussi essayé d'usurper l'en-tête Expires et Date (j'ai essayé de les supprimer, en les réglant de manière à ce qu'il y ait exactement la différence entre eux et en définissant Expires longtemps dans le futur). J'ai également expérimenté diverses valeurs de contrôle du cache, mais pas de chance.
J'ai vérifié que le fichier cacheFile existe, isDirectory et est accessible en écriture pour l'application.
Ce sont les en-têtes de requête et de réponse en direct par retrofit connecté:
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: ...
Et, enfin un incident étrange: à un moment donné, le cache a travaillé pendant quelques minutes. Je recevais un nombre de hits raisonnable, même les requêtes hors ligne renvoyaient des valeurs mises en cache. (C'est arrivé en utilisant le réglage exact affiché ici) Mais quand j'ai redémarré l'application, tout était redevenu "normal" (nombre de coups constant 0).
Co si quelqu'un a une idée de ce que pourrait être le problème ici, je serais vraiment heureux pour toute aide :)
Oh mon garçon, stupide moi. Merci beaucoup. Je dois avoir une sorte de cécité temporelle ou quelque chose - je n'ai jamais réalisé qu'il y a des intercepteurs() et pas networkInterceptors() dans ce code ... – daemontus