Retrofit + RxJava 缓存响应失败,疑似响应头
Retrofit + RxJava fails to cache responses, suspected response headers
我正在尝试使用 Retrofit 1.9.0
和 OkHtttp 2.5.0
配置缓存。
这是我为 RestAdapter
提供 OkHttpClient
的方式:
@Provides
@Singleton
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectTimeout(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
File cacheDir = new File(context.getCacheDir(), "http");
final Cache cache = new Cache(cacheDir, DISK_CACHE_SIZE_IN_BYTES);
okHttpClient.setCache(cache);
okHttpClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(request);
Response finalResponse = response.newBuilder()
.header("Cache-Control", String.format("public, max-stale=%d", 604800))
.build();
Log.d("OkHttp", finalResponse.toString());
Log.d("OkHttp Headers", finalResponse.headers().toString());
return finalResponse;
}
});
return okHttpClient;
}
我没有忘记 setClient
RestAdapter.Builder
。还要确保,我实际上是在使用此客户端集的 RestAdapter
实例。
甚至检查文件是否在 "http" 文件夹下创建。他们是。
然而,在我关闭 WIFI 并重新加载我的屏幕后,我最终在 Observable
端点的 OnError
回调中收到以下消息:
retrofit.RetrofitError: failed to connect to /10.40.31.12 (port 8888) after 10000ms: connect failed: ENETUNREACH (Network is unreachable)
免责声明:我应该提一下,最后的 Observable
是由其他 5 个组合而成的,还有 flatMap
和 zip
。
您应该重写 Request
而不是 Response
。作为参考,请参阅 rewriting requests. Note you, can also use the CacheControl
class 上的文档,而不是根据需要构建自己的 header。您的拦截器应该类似于 --
okHttpClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request cachedRequest = request.newBuilder()
.cacheControl(new CacheControl.Builder()
.maxStale(7, TimeUnit.DAYS)
.build())
.build();
return chain.proceed(cachedRequest);
}
});
我想我有答案了。短的一个是:"Cannot be done if server sends no-cache header in response"。
如果你想要更长的,详情如下。
我制作了一个比较 2 个后端的示例应用程序。让我们称它们为后端 A 和后端 B。A 给我带来了麻烦,所以我决定检查 B。
一个returnsCacheControl = "no-cache, no-transform, max-age=0"
B returns Cache-Control = „public"
回复 header
我对两个后端进行了相同的设置,只是 url 不同。
private void buildApi() {
Gson gson = new GsonBuilder().create();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
File cacheDir = new File(getCacheDir(), "http");
final Cache cache = new Cache(cacheDir, 1000000 * 10);
okHttpClient.setCache(cache);
okHttpClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Log.d("OkHttp REQUEST", request.toString());
Log.d("OkHttp REQUEST Headers", request.headers().toString());
Response response = chain.proceed(request);
response = response.newBuilder()
.header("Cache-Control", String.format("public, max-age=%d, max-stale=%d", 60, RESPONSE_CACHE_LIFESPAN_IN_SECONDS))
.build();
Log.d("OkHttp RESPONSE", response.toString());
Log.d("OkHttp RESPONSE Headers", response.headers().toString());
return response;
}
});
RestAdapter.Builder builder = new RestAdapter.Builder()
.setConverter(new StringGsonConverter(gson))
.setClient(new OkClient(okHttpClient))
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
if (isNetworkAvailable()) {
request.addHeader("Cache-Control", "public, max-age=" + 60);
} else {
request.addHeader("Cache-Control", "public, only-if-cached, max-stale=" + RESPONSE_CACHE_LIFESPAN_IN_SECONDS);
}
}
});
builder.setEndpoint("http://this.is.under.vpn.so.wont.work.anyway/api");
A_API = builder.build().create(AApi.class);
builder.setEndpoint("http://collector-prod-server.elasticbeanstalk.com/api");
B_API = builder.build().create(BApi.class);
}
打了两个电话,然后禁用了 wifi。
B 的缓存工作正常,但 A 抛出 504 Unsatisfiable Request (only-if-cached)
在这种情况下,覆盖 headers 似乎无济于事。
我正在尝试使用 Retrofit 1.9.0
和 OkHtttp 2.5.0
配置缓存。
这是我为 RestAdapter
提供 OkHttpClient
的方式:
@Provides
@Singleton
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectTimeout(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
File cacheDir = new File(context.getCacheDir(), "http");
final Cache cache = new Cache(cacheDir, DISK_CACHE_SIZE_IN_BYTES);
okHttpClient.setCache(cache);
okHttpClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(request);
Response finalResponse = response.newBuilder()
.header("Cache-Control", String.format("public, max-stale=%d", 604800))
.build();
Log.d("OkHttp", finalResponse.toString());
Log.d("OkHttp Headers", finalResponse.headers().toString());
return finalResponse;
}
});
return okHttpClient;
}
我没有忘记 setClient
RestAdapter.Builder
。还要确保,我实际上是在使用此客户端集的 RestAdapter
实例。
甚至检查文件是否在 "http" 文件夹下创建。他们是。
然而,在我关闭 WIFI 并重新加载我的屏幕后,我最终在 Observable
端点的 OnError
回调中收到以下消息:
retrofit.RetrofitError: failed to connect to /10.40.31.12 (port 8888) after 10000ms: connect failed: ENETUNREACH (Network is unreachable)
免责声明:我应该提一下,最后的 Observable
是由其他 5 个组合而成的,还有 flatMap
和 zip
。
您应该重写 Request
而不是 Response
。作为参考,请参阅 rewriting requests. Note you, can also use the CacheControl
class 上的文档,而不是根据需要构建自己的 header。您的拦截器应该类似于 --
okHttpClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request cachedRequest = request.newBuilder()
.cacheControl(new CacheControl.Builder()
.maxStale(7, TimeUnit.DAYS)
.build())
.build();
return chain.proceed(cachedRequest);
}
});
我想我有答案了。短的一个是:"Cannot be done if server sends no-cache header in response"。
如果你想要更长的,详情如下。
我制作了一个比较 2 个后端的示例应用程序。让我们称它们为后端 A 和后端 B。A 给我带来了麻烦,所以我决定检查 B。
一个returnsCacheControl = "no-cache, no-transform, max-age=0"
B returns Cache-Control = „public"
回复 header
我对两个后端进行了相同的设置,只是 url 不同。
private void buildApi() {
Gson gson = new GsonBuilder().create();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
File cacheDir = new File(getCacheDir(), "http");
final Cache cache = new Cache(cacheDir, 1000000 * 10);
okHttpClient.setCache(cache);
okHttpClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Log.d("OkHttp REQUEST", request.toString());
Log.d("OkHttp REQUEST Headers", request.headers().toString());
Response response = chain.proceed(request);
response = response.newBuilder()
.header("Cache-Control", String.format("public, max-age=%d, max-stale=%d", 60, RESPONSE_CACHE_LIFESPAN_IN_SECONDS))
.build();
Log.d("OkHttp RESPONSE", response.toString());
Log.d("OkHttp RESPONSE Headers", response.headers().toString());
return response;
}
});
RestAdapter.Builder builder = new RestAdapter.Builder()
.setConverter(new StringGsonConverter(gson))
.setClient(new OkClient(okHttpClient))
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
if (isNetworkAvailable()) {
request.addHeader("Cache-Control", "public, max-age=" + 60);
} else {
request.addHeader("Cache-Control", "public, only-if-cached, max-stale=" + RESPONSE_CACHE_LIFESPAN_IN_SECONDS);
}
}
});
builder.setEndpoint("http://this.is.under.vpn.so.wont.work.anyway/api");
A_API = builder.build().create(AApi.class);
builder.setEndpoint("http://collector-prod-server.elasticbeanstalk.com/api");
B_API = builder.build().create(BApi.class);
}
打了两个电话,然后禁用了 wifi。
B 的缓存工作正常,但 A 抛出 504 Unsatisfiable Request (only-if-cached)
在这种情况下,覆盖 headers 似乎无济于事。