改造:如何在没有 Content-Encoding 的情况下解析 GZIP 的响应:gzip header
Retrofit: how to parse GZIP'd response without Content-Encoding: gzip header
我正在尝试处理经过 GZIP 压缩的服务器响应。响应带有 header
Content-Type: application/x-gzip
但没有header
Content-Encoding: gzip
如果我使用代理添加 header,响应将得到很好的解析。
我对服务器没有任何控制权,所以我无法添加 header。
我可以强制 Retrofit 将其视为 GZIP 内容吗?有没有更好的办法?
服务器的 URL 是:
http://crowdtorch.cms.s3.amazonaws.com/4474/Updates/update-1.xml
我明白了。这个想法是添加一个自定义拦截器,它将接受 not-yet-unzipped 响应,并将其解压缩 'manually' - 做与 OkHttp 基于 Content-Encoding header 自动执行的相同的事情,但不需要 header.
就像dis:
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.addInterceptor(new UnzippingInterceptor());
OkHttpClient client = clientBuilder.build();
拦截器就像 dis:
private class UnzippingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return unzip(response);
}
}
并且解压功能如dis:
// 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();
}
有比重新发明轮子更好的方法。只需自己添加 Content-Encoding
header。
.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
没有那个构造函数了。
我正在尝试处理经过 GZIP 压缩的服务器响应。响应带有 header
Content-Type: application/x-gzip
但没有header
Content-Encoding: gzip
如果我使用代理添加 header,响应将得到很好的解析。 我对服务器没有任何控制权,所以我无法添加 header。
我可以强制 Retrofit 将其视为 GZIP 内容吗?有没有更好的办法? 服务器的 URL 是: http://crowdtorch.cms.s3.amazonaws.com/4474/Updates/update-1.xml
我明白了。这个想法是添加一个自定义拦截器,它将接受 not-yet-unzipped 响应,并将其解压缩 'manually' - 做与 OkHttp 基于 Content-Encoding header 自动执行的相同的事情,但不需要 header.
就像dis:
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.addInterceptor(new UnzippingInterceptor());
OkHttpClient client = clientBuilder.build();
拦截器就像 dis:
private class UnzippingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return unzip(response);
}
}
并且解压功能如dis:
// 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();
}
有比重新发明轮子更好的方法。只需自己添加 Content-Encoding
header。
.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
没有那个构造函数了。