Skip to content

Commit

Permalink
Enhance compression configuration with Builder
Browse files Browse the repository at this point in the history
- Refactor compression settings to use a Builder pattern for easier configuration and improved flexibility.
  • Loading branch information
raccoonback committed Jan 10, 2025
1 parent 7eee9c9 commit 99287f4
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 186 deletions.
22 changes: 17 additions & 5 deletions docs/modules/ROOT/pages/http-server.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,27 @@ You can configure the `HTTP` server to send a compressed response, depending on
* `compress(int)`: The compression is performed once the response size exceeds the given value (in bytes).
* `compress(BiPredicate<HttpServerRequest, HttpServerResponse>)`: The compression is performed if
the predicate returns `true`.
* `compressOptions(HttpCompressionOption... compressionOptions)`: Specifies the compression level for GZIP, DEFLATE, and ZSTD.
* `compressOptions(HttpCompressionOption... compressionOptions)`: Specifies the compression options for GZip, Deflate, and ZSTD.
+
[NOTE]
====
Supported Compression Levels
GZip Compression Options
* gzip : only the range 0 to 9 is allowed. (default: 6)
* deflate : only the range 0 to 9 is allowed. (default: 6)
* zstd : only the range -131072 to 22 is allowed. (default: 3)
* compression level : only the range 0 to 9 is allowed. (default: 6)
* window bits : only the range 0 to 9 is allowed. (default: 15)
* memory level : only the range 1 to 9 is allowed. (default: 8)
Deflate Compression Options
* compression level : only the range 0 to 9 is allowed. (default: 6)
* window bits : only the range 0 to 9 is allowed. (default: 15)
* memory level : only the range 1 to 9 is allowed. (default: 8)
ZSTD Compression Options
* compression level : only the range -131072 to 9 is allowed. (default: 3)
* block size : only the positive number is allowed. (default: 65536, that is 64KB)
* max encode size : only the positive number is allowed. (default: 33554432, that is 32MB)
====

The following example uses the `compress` method (set to `true`) to enable compression:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,15 +340,24 @@ public final HttpServer compress(int minResponseSize) {
}

/**
* Specifies GZIP, DEFLATE, ZSTD Compression Level.
* Specifies GZip, Deflate, ZSTD compression option
* with {@link reactor.netty.http.server.compression.GzipOption}, {@link reactor.netty.http.server.compression.DeflateOption}, , {@link reactor.netty.http.server.compression.ZstdOption}.
*
* @param compressionOptions configures {@link HttpCompressionOption} after enable compress.
*
* <pre>
* {@code
* HttpServer.create()
* .compress(true)
* .compress(true)
* .compressOptions(
* StandardHttpCompressionOptions.gzip(6, 15, 8)
* GzipOption.builder()
* .compressionLevel(6)
* .windowBits(15)
* .memoryLevel(8)
* .build(),
* ZstdOption.builder()
* .compressionLevel(3)
* .build()
* )
* .bindNow();
* }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,7 @@
*/
final class BrotliOption implements HttpCompressionOption {

private final CompressionOptions option;

BrotliOption() {
this.option = StandardCompressionOptions.brotli();
}

CompressionOptions adapt() {
return option;
return StandardCompressionOptions.brotli();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,107 @@

import io.netty.handler.codec.compression.CompressionOptions;
import io.netty.handler.codec.compression.StandardCompressionOptions;
import io.netty.util.internal.ObjectUtil;

/**
* Deflate compression option configuration.
*
* @author raccoonback
*/
final class DeflateOption implements HttpCompressionOption {
public final class DeflateOption implements HttpCompressionOption {

private final CompressionOptions option;
private final int compressionLevel;
private final int windowBits;
private final int memoryLevel;

DeflateOption() {
this.option = StandardCompressionOptions.gzip();
private DeflateOption(Build build) {
this.compressionLevel = build.compressionLevel;
this.windowBits = build.windowBits;
this.memoryLevel = build.memoryLevel;
}

DeflateOption(int compressionLevel, int windowBits, int memoryLevel) {
this.option = StandardCompressionOptions.gzip(
static DeflateOption provideDefault() {
return builder().build();
}

CompressionOptions adapt() {
return StandardCompressionOptions.deflate(
compressionLevel,
windowBits,
memoryLevel
);
}

CompressionOptions adapt() {
return option;
/**
* Creates a builder for {@link DeflateOption}.
*
* @return a new {@link DeflateOption.Builder}
*/
public static Builder builder() {
return new DeflateOption.Build();
}

public interface Builder {

/**
* Build a new {@link DeflateOption}.
*
* @return a new {@link DeflateOption}
*/
DeflateOption build();

/**
* Sets the deflate compression level.
*
* @return a new {@link DeflateOption.Builder}
*/
Builder compressionLevel(int compressionLevel);

/**
* Sets the deflate window bits.
*
* @return a new {@link DeflateOption.Builder}
*/
Builder windowBits(int windowBits);

/**
* Sets the deflate memory level.
*
* @return a new {@link DeflateOption.Builder}
*/
Builder memoryLevel(int memoryLevel);
}

private static final class Build implements Builder {

private int compressionLevel = 6;
private int windowBits = 12;
private int memoryLevel = 8;

@Override
public DeflateOption build() {
return new DeflateOption(this);
}

@Override
public Builder compressionLevel(int compressionLevel) {
ObjectUtil.checkInRange(compressionLevel, 0, 9, "compressionLevel");
this.compressionLevel = compressionLevel;
return this;
}

@Override
public Builder windowBits(int windowBits) {
ObjectUtil.checkInRange(windowBits, 9, 15, "windowBits");
this.windowBits = windowBits;
return this;
}

@Override
public Builder memoryLevel(int memoryLevel) {
ObjectUtil.checkInRange(memoryLevel, 1, 9, "memoryLevel");
this.memoryLevel = memoryLevel;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,107 @@

import io.netty.handler.codec.compression.CompressionOptions;
import io.netty.handler.codec.compression.StandardCompressionOptions;
import io.netty.util.internal.ObjectUtil;

/**
* GZIP compression option configuration.
*
* @author raccoonback
*/
final class GzipOption implements HttpCompressionOption {
public final class GzipOption implements HttpCompressionOption {

private final CompressionOptions option;
private final int compressionLevel;
private final int windowBits;
private final int memoryLevel;

GzipOption() {
this.option = StandardCompressionOptions.gzip();
private GzipOption(Build build) {
this.compressionLevel = build.compressionLevel;
this.windowBits = build.windowBits;
this.memoryLevel = build.memoryLevel;
}

GzipOption(int compressionLevel, int windowBits, int memoryLevel) {
this.option = StandardCompressionOptions.gzip(
static GzipOption provideDefault() {
return builder().build();
}

CompressionOptions adapt() {
return StandardCompressionOptions.gzip(
compressionLevel,
windowBits,
memoryLevel
);
}

CompressionOptions adapt() {
return option;
/**
* Creates a builder for {@link GzipOption}.
*
* @return a new {@link GzipOption.Builder}
*/
public static Builder builder() {
return new Build();
}

public interface Builder {

/**
* Build a new {@link GzipOption}.
*
* @return a new {@link GzipOption}
*/
GzipOption build();

/**
* Sets the gzip compression level.
*
* @return a new {@link GzipOption.Builder}
*/
Builder compressionLevel(int compressionLevel);

/**
* Sets the gzip window bits.
*
* @return a new {@link GzipOption.Builder}
*/
Builder windowBits(int windowBits);

/**
* Sets the gzip memory level.
*
* @return a new {@link GzipOption.Builder}
*/
Builder memoryLevel(int memoryLevel);
}

private static final class Build implements Builder {

private int compressionLevel = 6;
private int windowBits = 12;
private int memoryLevel = 8;

@Override
public GzipOption build() {
return new GzipOption(this);
}

@Override
public Builder compressionLevel(int compressionLevel) {
ObjectUtil.checkInRange(compressionLevel, 0, 9, "compressionLevel");
this.compressionLevel = compressionLevel;
return this;
}

@Override
public Builder windowBits(int windowBits) {
ObjectUtil.checkInRange(windowBits, 9, 15, "windowBits");
this.windowBits = windowBits;
return this;
}

@Override
public Builder memoryLevel(int memoryLevel) {
ObjectUtil.checkInRange(memoryLevel, 1, 9, "memoryLevel");
this.memoryLevel = memoryLevel;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@ public final class HttpCompressionOptionsSpec {
private ZstdOption zstd;

private HttpCompressionOptionsSpec() {
gzip = StandardHttpCompressionOptions.gzip();
deflate = StandardHttpCompressionOptions.deflate();
snappy = StandardHttpCompressionOptions.snappy();
gzip = GzipOption.provideDefault();
deflate = DeflateOption.provideDefault();
snappy = new SnappyOption();

if (Brotli.isAvailable()) {
brotli = StandardHttpCompressionOptions.brotli();
brotli = new BrotliOption();
}

if (Zstd.isAvailable()) {
zstd = StandardHttpCompressionOptions.zstd();
zstd = ZstdOption.provideDefault();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,7 @@
*/
final class SnappyOption implements HttpCompressionOption {

private final CompressionOptions option;

SnappyOption() {
this.option = StandardCompressionOptions.snappy();
}

CompressionOptions adapt() {
return option;
return StandardCompressionOptions.snappy();
}
}
Loading

0 comments on commit 99287f4

Please sign in to comment.