Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I used the POST request to access the server and DO NOT send data to the server while GET data from the server.

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

and I want to add a local cache for my data.

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();

When the network is connected,I can access the server,but when the network is not connected,my post will be intercept. And it will log the wrong:

HTTP 504 Unsatisfiable Request (only-if-cached)

I have checked the local cache path and it does have the "responses" folder that I built,and there is a file named "journal" in it.When I open it in text format,it is like this:

enter image description here

And I don't know how to solve it.

Hope anyone could help me!

like image 258
lixuan deng Avatar asked Mar 21 '17 12:03

lixuan deng


1 Answers

I search it for several day and I found the solution.

FIRST.change the POST request to the GET.

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

SECOND.Change the Inteceptor.

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);
    }
};

THIRD.the 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.the retrofit.

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

Now when the internet is connected,I got the cache.It is like this:

enter image description here

And the most important of all,do not forget to add this:

.removeHeader("Pragma")

or you will get the wrong of 504 again.

like image 196
lixuan deng Avatar answered Nov 13 '22 08:11

lixuan deng