Retrofit如何解析不带Content-Encoding:gzip头的GZIP压缩响应

7

我正在尝试处理一个被GZIP压缩的服务器响应。响应带有一个头部。

Content-Type: application/x-gzip

但是没有头部。
Content-Encoding: gzip

如果我使用代理添加头信息,响应会被成功解析。 但是我无法控制服务器,因此无法添加头信息。
我能否强制Retrofit将其视为GZIP内容?还有更好的方法吗? 服务器的URL为: http://crowdtorch.cms.s3.amazonaws.com/4474/Updates/update-1.xml
2个回答

12

我明白了。思路是添加一个自定义拦截器来获取未解压的响应,并手动进行解压 - 执行与 OkHttp 根据 Content-Encoding 头文件自动执行相同的操作,但不需要该头文件。

类似于这样:

    OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
            .addInterceptor(new UnzippingInterceptor());
    OkHttpClient client = clientBuilder.build();

而拦截器就像这样:

private class UnzippingInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        return unzip(response);
    }
}

并且解压函数是这样的:

    // copied from okhttp3.internal.http.HttpEngine (because is private)
private Response unzip(final Response response) throws IOException {

    if (response.body() == null) {
        return response;
    }

    GzipSource responseBody = new GzipSource(response.body().source());
    Headers strippedHeaders = response.headers().newBuilder()
            .removeAll("Content-Encoding")
            .removeAll("Content-Length")
            .build();
    return response.newBuilder()
            .headers(strippedHeaders)
            .body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody)))
            .build();
}

4

有一个比重新发明轮子更好的方法。只需自己添加Content-Encoding头。

.addNetworkInterceptor((Interceptor.Chain chain) -> {
    Request req = chain.request();
    Headers.Builder headersBuilder = req.headers().newBuilder();

    String credential = Credentials.basic(...);
    headersBuilder.set("Authorization", credential);

    Response res = chain.proceed(req.newBuilder().headers(headersBuilder.build()).build());

    return res.newBuilder()
        .header("Content-Encoding", "gzip")
        .header("Content-Type", ""application/json")
        .build();
})

事实上,你的代码是使用内部代码(例如来自JDK的com.sun包)的恶劣示例。 RealResponseBody不再具有该构造函数。


有趣。使用拦截器。好主意。听起来应该可以工作。 - itsymbal
@itsymbal 是的,我使用它。 - Abhijit Sarkar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接