Apache Commons HttpClient 是不是支持 GZIP?
Posted
技术标签:
【中文标题】Apache Commons HttpClient 是不是支持 GZIP?【英文标题】:Does Apache Commons HttpClient support GZIP?Apache Commons HttpClient 是否支持 GZIP? 【发布时间】:2011-02-16 03:38:15 【问题描述】:库 Apache Commons HttpClient 是否支持 Gzip?我们想在我们的 Apache 服务器上使用启用 gzip 压缩来加速客户端/服务器通信(我们有一个 php 页面,允许我们的 android 应用程序与服务器同步文件)。
【问题讨论】:
【参考方案1】:它不支持这种开箱即用的功能,而且似乎不太可能将其添加到 HttpClient 3.x 中(请参阅相当讨厌的 JIRA 问题here)。但是,您可以通过添加自定义请求阅读器和手动请求/响应流处理来实现这一点,分层在基本库之上,但这很繁琐。
您似乎可以使用 HttpClient 4 来做到这一点,但并非不费吹灰之力。
相当粗制滥造,如果你问我,这东西真的应该比它更容易。
【讨论】:
@karim79:我已经放弃了 HttpClient 由任何掌握现实的人维护的希望(好像 HttpClient 4 API 没有足够的证据)。【参考方案2】:Apache HttpClient 4.1 支持开箱即用的内容压缩以及许多以前被认为超出范围的其他功能。
【讨论】:
如何将其从盒子中取出? 在 4.5.3 中,只需通过 HttpClientBuilder.create().build() 使用客户端,它将为您处理所有 gzip 请求和响应解压。【参考方案3】:如果您的服务器能够提供 GZIPped 内容,那么您只需使用 Apache Http 客户端 4.1 即可
org.apache.http.impl.client.ContentEncodingHttpClient
这是DefaultHttpClient
的子类。
此客户端还将添加标头,表明它接受 GZIPped 内容。
【讨论】:
在 HttpClient 4.2.1 中,ContentEncodingHttpClient
已被弃用;鼓励用户使用 DecompressingHttpClient,见hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
@Hbf 也已弃用。
从 4.3 开始,应该使用HttpClientBuilder
(而不是ContentEncodingHttpClient
或DecompressingHttpClient
)。
使用HttpClientBuilder
,您是否必须调用构建器上的任何特定方法才能启用gzip?还是您根本不必打电话给disableContentCompression()
?
不,压缩是自动启用的。我用4.5.3试了一下,用wireshark抓取请求响应:请求中自动添加了“Accept-Encoding: gzip,deflate”头,可以自动解压响应内容。【参考方案4】:
Custom Protocol Interceptors 也可能有帮助。
免责声明:我还没有尝试过。
【讨论】:
【参考方案5】:它不支持开箱即用,但您可以通过调用将返回的HttpResponse
的实体转换为未压缩的实体
val entity = new GzipDecompressingEntity(response.getEntity)
然后像往常一样继续使用entity.getContent
。
【讨论】:
【参考方案6】:这是使用 java apache-http-client 库的示例 scala 代码
def createCloseableHttpClient(): CloseableHttpClient =
val builder: HttpClientBuilder = HttpClientBuilder.create
val closableClient = builder.build()
closableClient
def postData(data: String): Unit =
val entity = EntityBuilder.create()
.setText(data)
.setContentType(ContentType.TEXT_PLAIN)
.gzipCompress()
.build()
val post = new HttpPost(postURL + endPoint)
post.setEntity(entity)
post.setHeader("Content-Type", "application/gzip")
val client = createCloseableHttpClient()
client.execute(post)
client.close()
【讨论】:
【参考方案7】:自 4.1 起,Apache HttpClients 处理请求和响应压缩。
您无需压缩请求,无需在请求标头中设置任何“Accept-Encoding”。 它也会自动处理响应解压,无需处理响应解压。 到 4.3 为止,它可以处理 gzip 和 deflate。您可以查看ResponseContentEncoding
api doc here。
只需使用:
HttpClients.custom()
使用:
HttpClientBuilder.create()
如果你想签入库转到HttpClientBuilder
,它使用RequestAcceptEncoding
& ResponseContentEncoding
您可以通过“disableContentCompression()”禁用它
HttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.disableContentCompression() //this disables compression
.build();
请确保如果您添加任何可以覆盖的拦截器,请谨慎使用。
HttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.setHttpProcessor(httpprocessor) //this interceptor can override your compression.
.build();
【讨论】:
【参考方案8】:对于那些(像我一样)由于其他原因无法更新到 Apache 4.xx 并且需要拥有他们的 Apache 的人(顺便说一下,下面首先为 4.3.6 版本实现,但显然不支持“开箱即用”这可能是当然的,因为我们总是使用 custom 那些对我们的 httpclients 有其他特定要求的[“开箱即用”当然可以,如果您完全了解最新信息并且可以接受这个概念实际上会暗示 - 例如,默认重试策略、SSL 主机名验证、默认超时等对我们没有用不 - 如果您改用自定义,则 必须 了解你在做什么,从长远来看,这总是更好的......?])。无论如何,该解决方案也适用于 4.x.x 之前的版本——我在上面 Garry 的良好响应之后的示例行中添加了更多内容。使用 maven 构建,并在一般情况下容纳压缩响应,我已经添加了
<dependency>
<groupId>org.brotli</groupId>
<artifactId>dec</artifactId>
<version>0.1.2</version>
</dependency>
到我的 pom.xml。然后为了处理所有这三种常见的压缩方法(gzip、deflate 和 brotli),我在设置自定义 Apache HttpClient 时添加了拦截器 - 如下所示:
private static final String GZIP = "gzip";
private static final String DEFLATE = "deflate";
private static final String BR = "br";
private static final String ACCEPT_ENCODING = "Accept-Encoding";
private static final String SUPPORTED_COMPRESSION_VARIANTS = new StringBuilder(GZIP).append(COMMA_SPACE).append(DEFLATE).append(COMMA_SPACE).append(BR).toString();
private static final String COMMA_SPACE = ", ";
..
HttpClients.custom()..
.addInterceptorFirst((HttpRequestInterceptor) (request, context) -> // add accepting compressed headers _always_
if (!request.containsHeader(ACCEPT_ENCODING))
request.addHeader(ACCEPT_ENCODING, SUPPORTED_COMPRESSION_VARIANTS);
)
.addInterceptorFirst((HttpResponseInterceptor) (response, context) ->
HttpEntity entity = response.getEntity();
Header ceheader = entity != null ? entity.getContentEncoding() : null;
if (ceheader != null)
HeaderElement[] codecs = ceheader.getElements();
for (int i = 0; i < codecs.length; i++)
if (codecs[i].getName().equalsIgnoreCase(GZIP)) // handling gzip
response.setEntity(new GzipDecompressingEntity(response.getEntity()));
else if (codecs[i].getName().equalsIgnoreCase(DEFLATE)) // handling deflate
response.setEntity(new DeflateDecompressingEntity(response.getEntity()));
else if (codecs[i].getName().equalsIgnoreCase(BR)) // handling brotli
try (BufferedReader br =
new BufferedReader(new InputStreamReader(new BrotliInputStream(response.getEntity().getContent()))))
response.setEntity(new StringEntity(br.lines().collect(Collectors.joining())));
).build();
所以 - 这些的接受标头将始终添加到传出请求中,并且压缩响应由响应拦截器处理。工作正常。
【讨论】:
以上是关于Apache Commons HttpClient 是不是支持 GZIP?的主要内容,如果未能解决你的问题,请参考以下文章
commons-httpclient 和 httpclient 之间有啥关系,都来自 apache
tomcat下程序出现org.apache.commons.httpclient.HttpMethodDirector的错误