2

这个问题是针对 Apache Commons HttpClient 提出的,但是我使用的是异步客户端 HttpAsyncClient

内容解压缩 (gzip) 不能开箱即用。

我尝试使用以下方式对其进行配置:

httpClientAsync = HttpAsyncClients.custom()
            .setMaxConnPerRoute(100)
            .setMaxConnTotal(200)
            // Enable response content encoding (gzip)
            //
            // NOTE: Does not work for some reason
            .addInterceptorLast(ResponseContentEncoding())

我从中复制的HttpClientBuilder,但它不起作用。

有任何想法吗?

4

1 回答 1

2

使用addInterceptorLastaddInterceptorFirst没有效果。
asyncHttpClient.execute()默认情况下会创建一个BasicAsyncResponseConsumer
BasicAsyncResponseConsumer会将原始数据复制ContentDecoder到缓冲区中,从而导致DecompressingEntity.getContent()永远不会被调用。

org.apache.http.impl.nio.client.CloseableHttpAsyncClient#execute()

    public Future<HttpResponse> execute(
            final HttpHost target, final HttpRequest request, final HttpContext context,
            final FutureCallback<HttpResponse> callback) {
        return execute(
                HttpAsyncMethods.create(target, request),
                HttpAsyncMethods.createConsumer(), // BasicAsyncResponseConsumer
                context, callback);
    }

org.apache.http.nio.protocol.BasicAsyncResponseConsumer#onContentReceived

    protected void onContentReceived(
            final ContentDecoder decoder, final IOControl ioControl) throws IOException {
        Asserts.notNull(this.buf, "Content buffer");
        this.buf.consumeContent(decoder);
    }

我的解决方案是手动调用ResponseContentEncoding.process(resp, context)回调来重置 HttpEntity。

private static final ResponseContentEncoding responseContentEncoding = new ResponseContentEncoding();

HttpClientContext hcc = HttpClientContext.create();
asyncHttpClient.execute(bidreq, hcc, new FutureCallback<HttpResponse>() {
    @Override
    public void completed(HttpResponse result) {
        HttpEntity entity = null;
        String content = null;
        try {
            responseContentEncoding.process(result, hcc);
            entity = result.getEntity();
            if (entity != null) {
                content = EntityUtils.toString(entity, UTF_8);
                log.info(content);
            }
        } catch (Exception e) {
            log.error("error", e);
        } finally {
            EntityUtils.consumeQuietly(entity);
        }
    }

    @Override
    public void failed(Exception ex) {
        log.error("failed", ex);
    }

    @Override
    public void cancelled() { }
});
于 2020-05-28T07:32:26.603 回答