ProtocolException:太多后续请求:Android 中使用 Proguard 和 OkHttp 3.0 的 21 个

Posted

技术标签:

【中文标题】ProtocolException:太多后续请求:Android 中使用 Proguard 和 OkHttp 3.0 的 21 个【英文标题】:ProtocolException: Too many follow-up requests: 21 with Proguard and OkHttp 3.0 in Android 【发布时间】:2017-03-29 01:22:20 【问题描述】:

我正在使用 Retrofit 2.1.0 和 OkHttp 3.4.2 创建一个应用程序。

在调试模式下,将 minifyEnabled 设置为 false,一切正常,但是一旦我将 minifyEnabled 更改为 true,我就会得到以下异常:

HTTP FAILED: java.net.ProtocolException: Too many follow-up requests: 21

我的 OkHttp 的 Proguard 规则如下:

-keep class com.squareup.okhttp3.** 
    *;

-dontwarn okhttp3.**
-dontwarn okio.**

我不明白为什么会抛出这个异常,也不明白为什么应用程序似乎发出了 21 个跟进请求。谁能帮帮我?

【问题讨论】:

【参考方案1】:

我刚刚遇到了同样的错误:java.net.ProtocolException: Too many follow-up requests: 21。为了您的兴趣,我使用的是 Retrofit 2.5.0 和 OkHttp 3.14.1,尽管版本并不重要。

我也只有在启用 Proguard 时才会出现此错误(实际上我使用的是 R8,但结果是一样的)。这很重要,并暗示了根本原因。

有什么问题?我使用 OAuth 进行身份验证,像往常一样添加“授权”标头。当令牌过期时,服务器会发送 401 Unauthorized。由于我使用 OkHttp Authenticator 来刷新令牌,所以当收到 401 时会调用 authenticate 方法。

问题是我使用 Gson 解析这个 401 Unauthorized 请求的响应,像这样:

override fun authenticate(route: Route?, response: Response): Request? 
    val responseError: ResponseError? = response.body()?.let 
        Gson().fromJson(it.string(), ResponseError::class.java) // <- Fails!
    
    // Check server response and decide if should refresh token...

但是由于 ResponseError 类被 proguard 混淆了,它的字段与服务器发送的 JSON 的名称不匹配,这使得 Gson().fromJson 失败,因此令牌不是神清气爽。结果是重复执行网络调用,直到抛出异常。

修复很简单。只需将@Keep 添加到ResponseError

import androidx.annotation.Keep

@Keep
data class ResponseError(
    val error: String? = null,
    val error_description: String? = null
)

由于您的问题仅发生在启用 proguard 的情况下,因此请求或响应类可能被混淆,从而导致 JSON 解析失败。或者,您可能正在使用带有混淆类的 Gson.fromJsonGson.fromJson 将一些 JSON 保存到共享首选项。

要解决此问题,请将@SerializedName 和/或@Keep 添加到您的所有请求和响应中(特别是枚举,这会带来更多麻烦)。或者,您可以简单地将所有请求和响应放入一个包和exclude it。除了请求和响应之外,还要特别注意任何Gson.fromJsonGson.fromJson 呼叫。

为了帮助诊断问题,您可以通过检查在app/build/outputs/mapping/release/mapping.txt 中找到的映射文件(对于发布版本)来检查 proguard/R8 的功能。它包含 proguard/R8 对您的代码所做的所有转换。

您还可以通过 Build -> Analyze APK... 分析 APK... 您会以非常简单的方式查看哪些类被混淆了。您可以同时分析 2 个 APK(一个已缩小,一个未缩小)并进行比较。

【讨论】:

以上是关于ProtocolException:太多后续请求:Android 中使用 Proguard 和 OkHttp 3.0 的 21 个的主要内容,如果未能解决你的问题,请参考以下文章

在 Okhttp 中处理身份验证

java.net.ProtocolException:方法不支持请求正文:GET

收到太多后续请求作为请求的响应

WCF ProtocolException:错误请求 400(与 http 消息大小有关)

获取“java.net.ProtocolException:服务器重定向太多次”错误

使用 WCF Web 服务时获取 System.ServiceModel.ProtocolException