android - Retrofit+Okhttp.HTTP 504 Unsatisfiable Request (only-if-cached)

标签 android retrofit2 okhttp

我使用 POST 请求访问服务器并且在从服务器获取数据时不要向服务器发送数据。

@POST("Index/getListShopsInfo") Observable<ShopList> getListShopsInfo();

我想为我的数据添加一个本地缓存。

public class CacheInterceptor implements Interceptor {

    private Context mContext;

    public CacheInterceptor(Context context) {
        mContext = context;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        boolean netAvailable = AppUtils.isNetworkAvailable(mContext);
        if (netAvailable) {
            request = request.newBuilder()
                .cacheControl(CacheControl.FORCE_NETWORK)
                .build();
        } else {
        request = request.newBuilder()
            .cacheControl(CacheControl.FORCE_CACHE)
            .build();
        }
        Response response = chain.proceed(request);
        if (netAvailable) {
            response = response.newBuilder()
                .removeHeader("Pragma")
                .header("Cache-Control", "public, max-age=" + 60 * 60)
                .build();
        } else {
            response = response.newBuilder()
                .removeHeader("Pragma")
                .header("Cache-Control", "public, only-if-cached, max-stale=" + 7 * 24 * 60 * 60)
                .build();
        }
        return response;
    }
}


File cacheFile = new File(AppUtils.getDiskCacheDir(getContext()), "responses");
Cache cache = new Cache(cacheFile, App.DEFAULT_DIR_CACHE);
OkHttpClient client = new OkHttpClient().newBuilder()
    .addInterceptor(new CacheInterceptor(getContext()))
    .retryOnConnectionFailure(true)
    .connectTimeout(15, TimeUnit.SECONDS)
    .cache(cache)
    .build();`

mRetrofit = new Retrofit.Builder()
    .baseUrl(App.LOGINURL)
    .client(client)
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .build();

当网络连接时,我可以访问服务器,但是当网络不连接时,我的帖子将被拦截。它会记录错误:

HTTP 504 Unsatisfiable Request (only-if-cached)

我检查了本地缓存路径,确实有我建的“responses”文件夹,里面有一个名为“journal”的文件。当我以文本格式打开它时,它是这样的:

enter image description here

我不知道怎么解决。

希望有人能帮助我!

最佳答案

我搜索了几天,找到了解决方案。

首先,将 POST 请求更改为 GET。

@GET("Index/getListShopsInfo") Call<ShopList> getListShopsInfo();

其次。更改拦截器。

private final Interceptor REWRITE_RESPONSE_INTERCEPTOR = new Interceptor() {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        okhttp3.Response originalResponse = chain.proceed(chain.request());
        String cacheControl = originalResponse.header("Cache-Control");
        if (cacheControl == null || cacheControl.contains("no-store") || cacheControl.contains("no-cache") ||
                cacheControl.contains("must-revalidate") || cacheControl.contains("max-age=0")) {
            return originalResponse.newBuilder()
                    .removeHeader("Pragma")
                    .header("Cache-Control", "public, max-age=" + 5000)
                    .build();
        } else {
            return originalResponse;
        }
    }
};

private final Interceptor REWRITE_RESPONSE_INTERCEPTOR_OFFLINE = new Interceptor() {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        if (!AppUtils.isNetworkAvailable(getContext())) {
            request = request.newBuilder()
                    .removeHeader("Pragma")
                    .header("Cache-Control", "public, only-if-cached")
                    .build();
        }
        return chain.proceed(request);
    }
};

第三.okhttpClient.

File cacheFile = new File(AppUtils.getDiskCacheDir(getContext()), "FuckYouSecondDad");
    Cache cache = new Cache(cacheFile, App.DEFAULT_DIR_CACHE);
    OkHttpClient client = new OkHttpClient().newBuilder()
            .cache(cache)
            .addNetworkInterceptor(REWRITE_RESPONSE_INTERCEPTOR)
            .addInterceptor(REWRITE_RESPONSE_INTERCEPTOR_OFFLINE)
            .build();

FORTH.改造。

mRetrofit = new Retrofit.Builder()
            .baseUrl(App.LOGINURL)
            .client(mClient)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();

现在当互联网连接时,我得到了缓存。它是这样的:

enter image description here

最重要的是,不要忘记添加:

.removeHeader("Pragma")

不然又会报错504

关于android - Retrofit+Okhttp.HTTP 504 Unsatisfiable Request (only-if-cached),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42927216/

相关文章:

java - 在 Android 游戏中使用 Thread 或 TimerTask 的优缺点

android - 如何使用 OkHttp Android 避免 SSL 握手

android - 发送参数和主体行空改造

android - 改造httpLogInterceptor java.lang.NoSuchMethodError :

java - 通过 okhttp 客户端处理 woocommerce api 的签名基字符串时出现意外的 url

java - 在 Android 中创建和处理应用超时

java - 无法解析完成方法——从 Android Studio 方法调用

java - Android 定时任务(相当于cronjob)

android - Retrofit2 反序列化响应主体,即使响应不是 200

android - OKHTTP 无法解析主机 没有与主机名关联的地址