Retrofit/OkHttp 移除 Transfer-Encoding header

Retrofit/OkHttp removes Transfer-Encoding header

我需要我的请求包含 header Transfer-Encoding: chunked。但是无论我是用 @Headers 注释添加到方法还是用 @Header 注释和参数添加它,它都会从最终请求中消失。

@POST("/api/upload").                   // this header is added correctly
@Headers({"Transfer-Encoding: chunked", "Content-Type: application/foo"})
Call<UploadResponse> uploadFoo(@Body RequestBody body)

@POST("/api/upload").
@Headers("Content-Type: application/foo")
Call<UploadResponse> uploadFoo(@Body RequestBody body, @Header("Transfer-Encoding") te)

并称其为

uploadFoo(body, "chunked");

无效。

为什么改造会无缘无故地删除这个 header?

header 存在于拦截器中,顺便说一句。

Call object 的 originalRequest 字段也包含 header,但 Response object 的 rawResponse.request 没有,即使所有其他 header 都很好。

Retrofit 提供了两个选项来定义 HTTP 请求 header 字段:静态和动态。

通过这种方式你传递的是静态请求header,如果你使用日志拦截器

,你也可以在日志中看到这个header
@Headers({"Transfer-Encoding: chunked", "Content-Type: application/foo"})
@POST("/api/upload")                  
Call<UploadResponse> uploadFoo(@Body RequestBody body)

而第二种方式是动态传递header,你也可以在log

中看到这个header
@POST("/api/upload")
Call<UploadResponse> uploadFoo(@Body RequestBody body, @Header("Transfer-Encoding") String te)

最后但同样重要的是,如果你需要 header 字段在几乎每个请求中包含它的值,你可以使用拦截器来添加这条信息,比如

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();  
httpClient.addInterceptor(new Interceptor() {  
    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException {
        Request original = chain.request();

        // Request customization: add request headers
        Request.Builder requestBuilder = original.newBuilder()
                .header("Transfer-Encoding", "chunked"); // <-- this is the important line

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

OkHttpClient client = httpClient.build(); 

现在棘手的部分在这里,如果在你的拦截器中你使用这个 .header(key, val) 那么这将覆盖 headers,即使已经有一个现有的 header 具有相同的密钥标识符。您可以使用 .addHeader(key, val)

使用相同的密钥添加多个请求 header

根据文档,执行此操作的正常方法是在 @Body 之前使用 @Chunked 注释。

Call<UploadResponse> uploadFoo(@Chunked @Body RequestBody body)

您可以选择使用 Service 方法强制发送分块内容:

Service.sendChunked(@Chunked @Body Repo repo);

那些在 ChunkingConverter

中定义

不可能,OkHttp内部决定的,取决于RequestBody的类型