OKHttp Authenticator не работает с Retrofit приостановить удовольствие - PullRequest
2 голосов
/ 11 декабря 2019

Я недавно обновил Retrofit до 2.7.0 и OKHttp до 3.14.4, чтобы воспользоваться преимуществами приостановки на интерфейсах Retrofit.

Кроме того, я также пытаюсь реализовать Authenticator для логики токенов обновления.

Это интерфейс для модернизации

interface OfficeApi {
    @Authenticated
    @POST
    suspend fun getCharacter(): Response<CharacterResponse>
}

Это мой Аутентификатор

class CharacterAuthenticator : Authenticator {

    override fun authenticate(
        route: Route?,
        response: Response
    ): Request? {
        if (responseCount(response) >= 2) return null

        return response.request()
                        .newBuilder()
                        .removeHeader("Authorization")
                        .addHeader("Authorization", "Bearer $newToken")
                        .build()

        return null
    }

    private fun responseCount(response: Response?): Int {
        var result = 1
        while (response?.priorResponse() != null) result++
        return result
    }

}

Это забавный вызов для модернизации

    override suspend fun getCharacter() = safeApiCall(moshiConverter) {
        myApi.getCharacter()
    }

ЭтоsafeApiCall:

suspend fun <T> safeApiCall(
    moshiConverter: MoshiConverter,
    apiCall: suspend () -> Response<T>
): Result<T?, ResultError.NetworkError> {
    return try {
        val response = apiCall()
        if (response.isSuccessful) Result.Success(response.body())
        else {
            val errorBody = response.errorBody()
            val errorBodyResponse = if (errorBody != null) {
                moshiConverter.fromJsonObject(errorBody.string(), ErrorBodyResponse::class.java)
            } else null

            Result.Error(
                ResultError.NetworkError(
                    httpCode = response.code(),
                    httpMessage = response.message(),
                    serverCode = errorBodyResponse?.code,
                    serverMessage = errorBodyResponse?.message
                )
            )
        }
    } catch (exception: Exception) {
        Result.Error(ResultError.NetworkError(-1, exception.message))
    }
}

Аутентификатор работает правильно, дважды пытается обновить токен, а затем сдается. Проблема в том, что когда он сдается (возвращает ноль), выполнение модификации (функция safeApiCall) не продолжается. Я не имею никакой обратной связи, если звонок был успешным или нет.

Есть ли проблемы с использованием Authenticator и сопрограмм suspend fun?

Ответы [ 2 ]

1 голос
/ 11 декабря 2019

Разве это не бесконечный цикл?

while (response?.priorResponse() != null)

Разве это не должно быть

var curResponse: Response? = response
while (curResponse?.priorResponse() != null) {
    result++
    curResponse = curResponse.priorResponse()
}
0 голосов
/ 11 декабря 2019

Удалить приостановку попробуйте следующий код

fun getCharacter(): Response<CharacterResponse>
...