You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hc.apache.org by "Arturo Bernal (Jira)" <ji...@apache.org> on 2026/07/03 11:42:00 UTC
[jira] [Closed] (HTTPCLIENT-2426) NullPointerException in InflatingGzipDataConsumer kills I/O reactor when following redirects with Content-Encoding: gzip
[ https://issues.apache.org/jira/browse/HTTPCLIENT-2426?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Arturo Bernal closed HTTPCLIENT-2426.
-------------------------------------
> NullPointerException in InflatingGzipDataConsumer kills I/O reactor when following redirects with Content-Encoding: gzip
> ------------------------------------------------------------------------------------------------------------------------
>
> Key: HTTPCLIENT-2426
> URL: https://issues.apache.org/jira/browse/HTTPCLIENT-2426
> Project: HttpComponents HttpClient
> Issue Type: Bug
> Components: HttpClient (async)
> Affects Versions: 5.6.1
> Reporter: Szczepanski Dominik
> Priority: Major
> Fix For: 5.7-alpha1
>
> Original Estimate: 4h
> Time Spent: 0.5h
> Remaining Estimate: 3.5h
>
> h2. How to reproduce
> Make an async HTTP/1.1 request to an endpoint that responds with a 302 redirect where the intermediate response includes {{Content-Encoding: gzip}}. The I/O reactor thread dies with:
> {code}
> java.lang.NullPointerException
> at org.apache.hc.client5.http.async.methods.InflatingGzipDataConsumer.streamEnd(InflatingGzipDataConsumer.java:148)
> at org.apache.hc.client5.http.impl.async.HttpAsyncMainClientExec$1.failed(...)
> ...
> at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44)
> {code}
> h2. Why it fails
> When {{AsyncRedirectExec}} detects a redirect it returns {{null}} from {{handleResponse()}} — which I think is intentional with the meaning "discard this response body". The problem is that {{ContentCompressionAsyncExec}} passes the null downstream straight into {{InflatingGzipDataConsumer}}:
> {code:java}
> AsyncDataConsumer downstream = cb.handleResponse(rsp, wrapEntityDetails(details));
> for (int i = codecs.size() - 1; i >= 0; i--) {
> final String codec = codecs.get(i);
> final UnaryOperator<AsyncDataConsumer> op = decoders.lookup(codec);
> if (op != null) {
> downstream = op.apply(downstream);
> } else {
> throw new HttpException("Unsupported Content-Encoding: " + codec);
> }
> }
> {code}
> So when the redirect response has {{Content-Encoding: gzip}}, {{InflatingGzipDataConsumer}} gets instantiated with {{null}} as {{downstream}}. The class has no null checks, so once the body is drained and {{streamEnd()}} or {{releaseResources()}} is called it NPEs.
> h2. Fix
> Add null guards on {{downstream}} in {{updateCapacity()}}, {{consume()}}, {{streamEnd()}}, and {{releaseResources()}}. When {{downstream}} is null the body is being discarded anyway, so skipping the delegation seems to be the right behaviour.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org