Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a synchronous Retrofit call from inside an OkHttp Interceptor

I am trying to automatically refresh an auth token if it is expired. I am using the new Interceptor class that was introduced in OkHttp 2.2. In the intercept method I am trying the original request with chain.proceed(request), checking the response code, and if the token is expired I am making a call to a separate Retrofit service, synchronously, to obtain a new token.

The strange thing is, no code past the synchronous call seems to run. If I try debugging with a breakpoint on the synchronous call's line, then do a step-over, I am stopped in Dispatcher.java at :

if (!executedCalls.remove(call)) throw new AssertionError("Call wasn't in-flight!");

Any idea as to what I might be doing wrong here? I could probably just craft a new request by hand, but I am just kind of curious why a Retrofit call doesn't seem to work here.

My Interceptor:

public class ReAuthInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        // try the request
        Response response = chain.proceed(request);

        // if we receive a "401 - Not Authorized" then refresh the auth token and try again
        if (response.code() == 401) {
            // get a new auth token and store it
            UserToken userToken = MobileClient.getOkraService().login(AuthUtil.getUserToken(MSWorksApplication.getContext()));
            AuthUtil.authenticate(MSWorksApplication.getContext(), userToken);

            Log.d("TEST", "TEST TEST TEST");

            // use the original request with the new auth token
            Request newRequest = request.newBuilder().header("Authorization", AuthUtil.getAuthToken(MSWorksApplication.getContext())).build();

            return chain.proceed(newRequest);
        }
        else {
            // the auth token is still good
            return response;
        }
    }
}
like image 658
theblang Avatar asked Jan 29 '15 23:01

theblang


People also ask

How do I put the OkHttp interceptor in retrofit?

Interceptor Types These are the interceptors that we add with addInterceptor(). Interceptors on the network: These are interceptors placed between the OkHttp Core Library and the server. These can be added to OkHttpClient by using the addNetworkInterceptor command ().

Does retrofit run on background thread?

Retrofit is a third-party library by Square for communicating with REST APIs over HTTP. Similarly to AsyncTasks , work is done in a background thread, and upon completion it returns the result to the main UI thread. To use Retrofit, declare a service using a simple interface with annotated methods.

Is retrofit synchronous?

Learn to execute synchronous and asynchronous calls (i.e. blocking and non-blocking calls) in an android app using Retrofit2 and OkHttp library.

What is Retrofit2 call?

Uses of Call in retrofit2Returns an instance of T which delegates to call . void. Callback. onFailure(Call<T> call, Throwable t) Invoked when a network exception occurred talking to the server or when an unexpected exception occurred creating the request or processing the response.


1 Answers

I had this problem - if you're getting an HTTP response code that would cause Retrofit to call failure() instead of success() an exception will be thrown.

If you wrap

UserToken userToken = MobileClient.getOkraService().login(AuthUtil.getUserToken(MSWorksApplication.getContext()));

in a try/catch(RetrofitError e) you'll be able to execute code after a failure, however I've found this to be quite cumbersome and am still in the process of finding a nicer solution.

like image 102
Samuel Jones Avatar answered Oct 15 '22 00:10

Samuel Jones