Okhttp + Retrofit @Body 请求 - 传输编码:添加了分块

Posted

技术标签:

【中文标题】Okhttp + Retrofit @Body 请求 - 传输编码:添加了分块【英文标题】:Okhttp + Retrofit @Body request - Transfer-Encoding: chunked added 【发布时间】:2018-06-26 03:54:18 【问题描述】:

我在 android 中使用 Retrofit 和 Okhttp 时遇到问题。问题是当我使用带有正文有效负载的请求时,会自动添加标头Transfer-Encoding: chunked,如下所示:

@POST("members")
Observable<Response<Void>> createMember(@Header(X_CLIENT_AUTHORIZATION) 
String clientAuthorization, @Body RequestBody payload);

然后,自动添加标题Transfer-Encoding: chunked,由于某种原因,服务器无法处理。我希望正文是纯文本 json。服务器认为它是我猜的文件。

最糟糕的是,如果我尝试添加拦截器并使用 removeHeader 甚至都不起作用。

httpClient.addInterceptor(new Interceptor() 
    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException 
       Request original = chain.request();
       Request.Builder requestBuilder = original.newBuilder()
               .removeHeader("Transfer-Encoding");

       Request request = requestBuilder.build();
       return chain.proceed(request);
   
);

我希望能够发送带有RequestBody 但没有chunked 标头的@POST...

如果我这样使用它就不会添加标题:

@POST("members")
Observable<Response<Void>> createMember(@Header(X_CLIENT_AUTHORIZATION) String clientAuthorization, @Body **String** payload);

但我想避免在发送之前将所有对象解析为String

有谁知道如何删除此类请求并将对象作为纯文本 json 发送?

【问题讨论】:

【参考方案1】:

Transfer-encoding: chunked 在 Retrofit 事先不知道你的请求正文的完整长度时使用。 IE。当 RequestBody.contentLength() 返回 -1。您需要编写一些代码,将未知长度的 RequestBody 转换为已知长度的 RequestBody。你也许可以这样做:

RequestBody original = ...
Buffer buffer = new Buffer();
original.writeTo(buffer);
ByteString bytes = buffer.snapshot();
RequestBody fixedLength = RequestBody.create(bytes, original.contentType());

如果您在拦截器中执行此操作,您甚至不需要更改调用代码。

【讨论】:

该死的就是这样。谢谢你:) 在我的例子中,我决定用 @SerializedName 注释来包装正文,这样它的创建方式就会有点不同,就像这样:nopaste.xyz/…

以上是关于Okhttp + Retrofit @Body 请求 - 传输编码:添加了分块的主要内容,如果未能解决你的问题,请参考以下文章

Retrofit2 完全解析 探索与okhttp之间的关系

Retrofit2 完全解析 探索与okhttp之间的关系

Retrofit2源码解读

手动缓存Retrofit+OkHttp响应体,不再局限于Get请求缓存

Retrofit+OkHttp中如何正确的使用https?

Retrofit+OkHttp中如何正确的使用https?