OKHttp Authenticator 不适用于 Retrofit 暂停乐趣

Posted

技术标签:

【中文标题】OKHttp Authenticator 不适用于 Retrofit 暂停乐趣【英文标题】:OKHttp Authenticator not working with Retrofit suspend fun 【发布时间】:2020-04-05 00:38:46 【问题描述】:

我最近将 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))
    

Authenticator 工作正常,尝试刷新令牌两次然后放弃。问题是:当它放弃时(返回null),改造(safeApiCall函数)的执行不会继续。如果通话成功与否,我没有任何反馈。

使用Authenticator和Coroutinessuspend fun有什么问题吗?

【问题讨论】:

可能在这里看到我的答案,这是对您的问题的暂定“是”。我从协程切换到 Call 请求取得了更大的成功。 ***.com/questions/62950438/… 【参考方案1】:

这不是无限循环吗?

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

不应该

var curResponse: Response? = response
while (curResponse?.priorResponse() != null) 
    result++
    curResponse = curResponse.priorResponse()

【讨论】:

【参考方案2】:

删除挂起试试下面的代码

fun getCharacter(): Response<CharacterResponse>

【讨论】:

整个想法是使用来自 Retrofit 的新的挂起乐趣支持,因此删除不是一种选择。

以上是关于OKHttp Authenticator 不适用于 Retrofit 暂停乐趣的主要内容,如果未能解决你的问题,请参考以下文章

SPDY 不适用于 OkHttp

证书固定不适用于 Android 上的 OkHttp

Error: Program type already present: okhttp3.Authenticator$1

http2 似乎不适用于 OkHttp3 和 retrofit2

OkHttp3基本认证(Basic Authentication)

向服务器发送多个请求时,Okhttp 刷新过期令牌