Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a problem doing another API call inside interceptor in Android?

I have an issue where I am trying to refresh an access token inside my interceptor. I have read it is better to use an Authenticator for this issue, but the way my API works is that I get a 403 error for an unauthorized access token (not my design but gotta work with it).

So I am trying to call the API endpoint to get a new access token inside my interceptor but it seems like the second API call creates an OKHTTP Response without closing it.

override fun intercept(chain: Interceptor.Chain?): Response {

        var currentRequest = chain!!.request()
        val currentRequestResponse = chain.proceed( currentRequest )

        if ( currentRequestResponse.code() >= HTTP_ERROR_CODE && isNotLoginRequest( chain ) ) {

            try {

                // we check the response code, if there is 403 code we need to relog the user
                // before executing the request
                // try to reconnect the user with synchronous request


                val userManager = UserManager.getInstance()

                val clientId = getQueryParameter(UserService.CLIENT_ID_QUERY_KEY, currentRequest)
                val redirectUri = getQueryParameter(UserService.REDIRECT_URI_QUERY_KEY, currentRequest)
                val clientSecret = getQueryParameter(UserService.CLIENT_SECRET_QUERY_KEY, currentRequest)

                // we get a new access token with a synchronous request
                val accessToken = userManager.refreshToken(clientId, clientSecret, redirectUri)

                currentRequest = rebuildRequestWithNewToken( accessToken, currentRequest )

                return chain.proceed( currentRequest )

            } catch (e: Throwable) {

                e.printStackTrace()
            }
        }

        return currentRequestResponse
    }

I believe the problem comes from the userManager.refreshToken which is the API call to get the new access token.

Here is the error I receive:

java.lang.IllegalStateException: cannot make a new request because the previous response is still open: please call response.close()

like image 838
Thibault Charriere Avatar asked Jul 31 '19 15:07

Thibault Charriere


People also ask

Why interceptors are used in Android?

Interceptors, according to the documentation, are a powerful mechanism that can monitor, rewrite, and retry the API call. So, when we make an API call, we can either monitor it or perform some tasks.

Why use Retrofit in Android?

Retrofit is used to perform the following tasks: It manages the process of receiving, sending, and creating HTTP requests and responses. It alternates IP addresses if there is a connection to a web service failure. It caches responses to avoid sending duplicate requests.

What is Retrofit library Android?

Retrofit is a type-safe REST client for Android, Java and Kotlin developed by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.


1 Answers

You can make the refresh token call inside the network interceptor like this

if (response.code() == 403) {
            try {
                val body = RequestBody.create(contentType, "")

                val authRequest = request.newBuilder()
                        .setDefaultHeaders()
                        .addHeader("Authorization", "Your token")
                        .url(refreshtokenurl)
                        .post(body)
                        .build()
                val tokenRefreshResponse = chain.proceed(authRequest)
                if (tokenRefreshResponse.code() == 401 || tokenRefreshResponse.code() == 403) {
                   //error in refreshing token
                } else if (tokenRefreshResponse.code() == 200) {
                   //save the new token and refresh token in preference and continue with the earlier request
                    currentRequestResponse = chain.proceed(currentRequest.newBuilder()
                                .setDefaultHeaders()
                                .addHeader(your header)
                                .build())
                }
            } catch (e: Exception) {

            }

        }

like image 62
Rajat Beck Avatar answered Oct 20 '22 02:10

Rajat Beck