Skip to content

Commit

Permalink
Makes Brotli more native compilation friendly (#12409)
Browse files Browse the repository at this point in the history
Motivation:
CompressorHttp2ConnectionEncoder shouldn't load anything specific to Brotli if it isn't available

Modification:
Allows a null Brotli option to be passed to CompressorHttp2ConnectionEncoder

Result:
GraalVM Native compilation without Brotli doesn't requires Brotli classes
  • Loading branch information
franz1981 authored and normanmaurer committed Jun 1, 2022
1 parent 2e91917 commit a2f101a
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 7 deletions.
Expand Up @@ -174,8 +174,13 @@ public HttpContentCompressor(int contentSizeThreshold, CompressionOptions... com
} else {
ObjectUtil.deepCheckNotNull("compressionOptions", compressionOptions);
for (CompressionOptions compressionOption : compressionOptions) {
if (compressionOption instanceof BrotliOptions) {
// if we have BrotliOptions, it means Brotli is available
// BrotliOptions' class initialization depends on Brotli classes being on the classpath.
// The Brotli.isAvailable check ensures that BrotliOptions will only get instantiated if Brotli is
// on the classpath.
// This results in the static analysis of native-image identifying the instanceof BrotliOptions check
// and thus BrotliOptions itself as unreachable, enabling native-image to link all classes
// at build time and not complain about the missing Brotli classes.
if (Brotli.isAvailable() && compressionOption instanceof BrotliOptions) {
brotliOptions = (BrotliOptions) compressionOption;
} else if (compressionOption instanceof GzipOptions) {
gzipOptions = (GzipOptions) compressionOption;
Expand Down Expand Up @@ -205,7 +210,8 @@ public HttpContentCompressor(int contentSizeThreshold, CompressionOptions... com
this.factories.put("deflate", ZlibCompressor.newFactory(
ZlibWrapper.ZLIB, deflateOptions.compressionLevel()));
}
if (this.brotliOptions != null) {

if (Brotli.isAvailable() && this.brotliOptions != null) {
this.factories.put("br", BrotliCompressor.newFactory(brotliOptions.parameters()));
}
if (this.zstdOptions != null) {
Expand Down
Expand Up @@ -18,6 +18,7 @@
import io.netty5.channel.ChannelHandlerContext;
import io.netty5.channel.embedded.EmbeddedChannel;
import io.netty5.handler.codec.ByteToMessageDecoder;
import io.netty5.handler.codec.compression.Brotli;
import io.netty5.handler.codec.compression.BrotliCompressor;
import io.netty5.handler.codec.compression.BrotliOptions;
import io.netty5.handler.codec.compression.CompressionOptions;
Expand Down Expand Up @@ -74,8 +75,7 @@ public class CompressorHttp2ConnectionEncoder extends DecoratingHttp2ConnectionE
* with default implementation of {@link StandardCompressionOptions}
*/
public CompressorHttp2ConnectionEncoder(Http2ConnectionEncoder delegate) {
this(delegate, StandardCompressionOptions.brotli(), StandardCompressionOptions.gzip(),
StandardCompressionOptions.deflate());
this(delegate, defaultCompressionOptions());
}

/**
Expand Down Expand Up @@ -114,7 +114,13 @@ public CompressorHttp2ConnectionEncoder(Http2ConnectionEncoder delegate,
ObjectUtil.deepCheckNotNull("CompressionOptions", compressionOptionsArgs);

for (CompressionOptions compressionOptions : compressionOptionsArgs) {
if (compressionOptions instanceof BrotliOptions) {
// BrotliOptions' class initialization depends on Brotli classes being on the classpath.
// The Brotli.isAvailable check ensures that BrotliOptions will only get instantiated if Brotli is on
// the classpath.
// This results in the static analysis of native-image identifying the instanceof BrotliOptions check
// and thus BrotliOptions itself as unreachable, enabling native-image to link all classes at build time
// and not complain about the missing Brotli classes.
if (Brotli.isAvailable() && compressionOptions instanceof BrotliOptions) {
brotliOptions = (BrotliOptions) compressionOptions;
} else if (compressionOptions instanceof GzipOptions) {
gzipCompressionOptions = (GzipOptions) compressionOptions;
Expand Down Expand Up @@ -142,6 +148,16 @@ public void onStreamRemoved(Http2Stream stream) {
});
}

private static CompressionOptions[] defaultCompressionOptions() {
if (Brotli.isAvailable()) {
return new CompressionOptions[] {
StandardCompressionOptions.brotli(),
StandardCompressionOptions.gzip(),
StandardCompressionOptions.deflate() };
}
return new CompressionOptions[] { StandardCompressionOptions.gzip(), StandardCompressionOptions.deflate() };
}

@Override
public Future<Void> writeData(final ChannelHandlerContext ctx, final int streamId, ByteBuf data, int padding,
final boolean endOfStream) {
Expand Down Expand Up @@ -248,7 +264,7 @@ protected Compressor newContentCompressor(ChannelHandlerContext ctx, CharSequenc
if (DEFLATE.contentEqualsIgnoreCase(contentEncoding) || X_DEFLATE.contentEqualsIgnoreCase(contentEncoding)) {
return newCompressionChannel(ctx, ZlibWrapper.ZLIB);
}
if (brotliOptions != null && BR.contentEqualsIgnoreCase(contentEncoding)) {
if (Brotli.isAvailable() && brotliOptions != null && BR.contentEqualsIgnoreCase(contentEncoding)) {
return BrotliCompressor.newFactory(brotliOptions.parameters()).get();
}
if (zstdOptions != null && ZSTD.contentEqualsIgnoreCase(contentEncoding)) {
Expand Down

0 comments on commit a2f101a

Please sign in to comment.