Twitter oauth / request_token 200代码,响应主体为空

时间:2020-09-23 09:48:38

标签: android kotlin twitter gson retrofit

我正在按照以下方式实施Twitter OAuth流:

https://developer.twitter.com/en/docs/authentication/guides/log-in-with-twitter

我收到第一步(oauth / request_token)的响应,该响应具有200个代码,但是响应主体完全为空。

我正在使用Retrofit来调用API,并且已经连接了一个拦截器OkHttpClient来调试响应,如下所示:

val client = OkHttpClient.Builder().also { builder ->
    builder.addInterceptor { chain ->
        val request = chain.request()
        val response = chain.proceed(request)
        response
    }
}.build()

然后按如下所示设置Retrofit:

Retrofit.Builder()
                .baseUrl(TWITTER_AUTH_BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build()
                .create(TwitterAuthRetrofit::class.java)
                .getRequestToken(
                       authorizationHeaders
                ).enqueue(object : Callback<TwitterRequestToken> {
                    override fun onResponse(call: Call<TwitterRequestToken>, response: Response<TwitterRequestToken>) {
                        onSuccess(response.body())
                    }

                    override fun onFailure(call: Call<TwitterRequestToken>, t: Throwable) {
                        onFailure()
                    }
                })

当我在拦截器中调试时,可以看到响应成功(200),但是响应主体为空,我认为这导致我的Gson反序列化失败。

在拦截器中调用response.body.contentLength()的结果为-1。

在拦截器中调用response.code的结果为200。

这是我尝试反序列化响应主体的模型:

data class TwitterRequestToken(
        @SerializedName(value = "oauth_token")
        val token: String,
        @SerializedName(value = "oauth_token_secret")
        val tokenSecret: String,
        @SerializedName(value = "oauth_callback_confirmed")
        val callbackConfirmed: Boolean
)

请注意,我正在使用@SerializedName提供响应正文的密钥,而我的属性名称对于我们的应用程序是任意的(我们使用驼峰式大小写)。我使用构建器将GsonConverterFactory添加到了Retrofit实例中,并且对于其他许多请求,都以相同的方式完成了此操作,之前没有问题。

这是我从API中获得的响应,我正在通过上面的拦截器中的调试来查看响应:

Response{protocol=h2, code=200, message=, url=https://api.twitter.com/oauth/request_token}

这是来自cause的{​​{1}}消息,我正在从Retrofit中收到Throwable回调:

onFailure

有人知道这可能是什么原因吗?

1 个答案:

答案 0 :(得分:0)

最后弄清楚了,希望这对以后的人有帮助...

Twitter API的oauth / request_token响应主体未编码为JSON;您将需要从响应缓冲区中读取它。具体来说,在使用Retrofit实现API时,您希望您的Retrofit接口返回ResponseBody(而不是自定义类),从Retrofit构建器中删除GSON,然后在Retrofit的onResponseCallback中编写以下代码将缓冲区读取为字符串,然后在&上拆分字符串以获取每个键val对,然后可以在=上拆分每个键并确保在构造之前拥有所有3个值您的模型:

override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                        response.body()?.also { body ->
                            body.source().readString(Charsets.UTF_8).split('&').map { param ->
                                param.split('=').let { keyVal ->
                                    keyVal[0] to keyVal[1]
                                }
                            }.toMap().let { paramMap ->
                                val oauthToken = paramMap["oauth_token"]
                                val oauthTokenSecret = paramMap["oauth_token_secret"]
                                val oauthCallbackConfirmed = paramMap["oauth_callback_confirmed"]?.toBoolean()
                                if (oauthToken == null || oauthTokenSecret == null || oauthCallbackConfirmed == null) {
                                    onFailure()
                                } else {
                                    onSuccess(
                                            TwitterRequestToken(
                                                    oauthToken,
                                                    oauthTokenSecret,
                                                    oauthCallbackConfirmed
                                            )
                                    )
                                }
                            }
                        } ?: onFailure()
                    }