Skip to content

Conversation

@arturobernalg
Copy link
Member

@arturobernalg arturobernalg commented Jul 18, 2025

This patch fulfils HTTPCLIENT-1822 by delivering transparent (de)compression support in the async pipeline.

DecompressingStringAsyncEntityConsumer – decodes gzip/deflate/brotli/zstd … responses using the codecs in ContentCodecRegistry and returns the plain body as a String.

CompressingAsyncEntityProducer – wraps any outgoing producer and re-encodes its payload with the chosen Content-Encoding, also via ContentCodecRegistry; enables gzip (or other) uploads.

AsyncClientDecompressionExample shows response-side usage. AsyncClientCompressionExample demonstrates gzip uploads.

With these additions an async client can both receive and send compressed entities without extra boiler-plate.

@arturobernalg arturobernalg requested a review from ok2c July 18, 2025 13:06
@ok2c
Copy link
Member

ok2c commented Jul 21, 2025

@arturobernalg I am not sure about this one. I would prefer a proper solution (even if it is GZIP only) without full content buffering or nothing at all.

@arturobernalg
Copy link
Member Author

without full content buffering or nothing at all

@ok2c I've implemented streaming DEFLATE and GZIP compression/decompression without full content buffering, . I'm not sure if this fully aligns with what you requested.

if (coding == null) {
throw new IOException("Unknown coding: " + token);
}
final java.util.function.UnaryOperator<HttpEntity> op = ContentCodecRegistry.encoder(coding);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't need to be a fully qualified name.

}

private GzipState state = GzipState.HEADER_MAGIC1;
private int flags = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should initialize instance variables to default values (like in C!), it feels like clutter.

@ok2c
Copy link
Member

ok2c commented Jul 24, 2025

@arturobernalg I am not in a position to tell you what to do. At the moment I see only DeflateCompressingAsyncEntityProducer as promising.

Why does DeflateDecompressingStringAsyncEntityConsumer work with Strings only? Could not it work with any arbitrary EntityConsumer?

I would focus on these two classes for now and drop the rest.

@arturobernalg
Copy link
Member Author

arturobernalg commented Jul 24, 2025

@arturobernalg I am not in a position to tell you what to do. At the moment I see only DeflateCompressingAsyncEntityProducer as promising.

Why does DeflateDecompressingStringAsyncEntityConsumer work with Strings only? Could not it work with any arbitrary EntityConsumer?

I would focus on these two classes for now and drop the rest.

@ok2c please do another pass. I'll implement the gzip in another PR>

@ok2c
Copy link
Member

ok2c commented Jul 25, 2025

@arturobernalg I guess I failed to properly express myself. I actually thought you were going to build DeflatingAsyncEntityProducer and InflatingAsyncEntityCunsumer using Deflater / Inflater API directly without any of InputStream / OutputStream code that basically does not work well with async transport. I can still see HttpEntity / InputStream / OutputStream all over the place. I cannot stop you but i do not find such implementations very useful.

@arturobernalg
Copy link
Member Author

build DeflatingAsyncEntityProducer and InflatingAsyncEntityCunsumer using Deflater / Inflater API directly

@ok2c implemented.

Copy link
Member

@ok2c ok2c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg DeflatingAsyncEntityProducer and InflatingAsyncEntityCunsumer look good.

I would drop CompressingAsyncEntityProducer.

Could you also add an async version of ContentCompressionExec to the request execution pipeline?

Copy link
Member

@ok2c ok2c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg Very good otherwise.

Copy link
Member

@ok2c ok2c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg Almost there.

}

String coding = details != null ? details.getContentEncoding() : null;
if (coding == null && rsp.containsHeader(HttpHeaders.CONTENT_ENCODING)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg Please use details#getContentEncoding() only. It is the only attribute that is relevant here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg This stills needs to be fixed.


@Override
public String getContentType() {
return original != null ? original.getContentType() : null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg original should never be nulll here. We cannot make an entity if there was none to begin with.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg What about #getTrailerNames?

Copy link
Member

@ok2c ok2c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg Two things still need to be fixed.

Alternatively I can pull in your change, tweak them a bit and commit it.

…ngAsyncEntityProducer and InflatingAsyncEntityCunsumer using Deflater / Inflater API directly
@arturobernalg
Copy link
Member Author

@arturobernalg Two things still need to be fixed.

Alternatively I can pull in your change, tweak them a bit and commit it.

@ok2c I just made the missing change. Please feel free to do any tweak that you think is need it.

@arturobernalg arturobernalg requested a review from ok2c August 4, 2025 16:44
@ok2c
Copy link
Member

ok2c commented Aug 5, 2025

Committed as 3fbbd22.

@arturobernalg Very good job

@ok2c ok2c closed this Aug 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants