Nikola Mihajlović
Nikola Mihajlović

Reputation: 2465

Does Apache Commons HttpAsyncClient support GZIP?

This question was asked for Apache Commons HttpClient, however I'm using the async client HttpAsyncClient.

Content decompression (gzip) does not work out of the box.

I tried to configure it with:

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

Which I copied from HttpClientBuilder, but it doesn't work.

Any ideas?

Upvotes: 2

Views: 619

Answers (1)

Wayne
Wayne

Reputation: 31

The use of addInterceptorLast and addInterceptorFirst has no effect.
asyncHttpClient.execute() will create a BasicAsyncResponseConsumer by default.
This BasicAsyncResponseConsumer will copy the original ContentDecoder into the buffer, resulting in DecompressingEntity.getContent() is never called.

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);
    }

My solution is to manually call ResponseContentEncoding.process(resp, context) in the callback to reset the 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() { }
});

Upvotes: 2

Related Questions