Skip to content

Commit f86ea16

Browse files
committed
Introduce HttpCompressionOptions.
Motivation: HTTP/3 will require configure of compression. This introduces a new HttpCompressionOptions configuration that encapsulate anything related to compression configuration. Changes: The HttpServerConfiguration is modified to use this setting and delegate the current related methods to the underlying compression object to support the transition. HTTP compression tests have been reworked to use the new HTTP configuration mechanism and reduce the proliferation of test subclasses to reduce the amount of necessary code to test the variety of algorithms.
1 parent f56b75f commit f86ea16

17 files changed

+465
-402
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright (c) 2011-2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
package io.vertx.core.http;
12+
13+
import io.netty.handler.codec.compression.CompressionOptions;
14+
import io.vertx.codegen.annotations.DataObject;
15+
import io.vertx.core.impl.Arguments;
16+
17+
import java.util.ArrayList;
18+
import java.util.List;
19+
20+
/**
21+
* HTTP compression configuration.
22+
*/
23+
@DataObject
24+
public class HttpCompressionOptions {
25+
26+
private int contentSizeThreshold;
27+
private List<CompressionOptions> compressors;
28+
29+
public HttpCompressionOptions() {
30+
this.contentSizeThreshold = HttpServerOptions.DEFAULT_COMPRESSION_CONTENT_SIZE_THRESHOLD;
31+
this.compressors = null;
32+
}
33+
34+
public HttpCompressionOptions(HttpCompressionOptions other) {
35+
this.contentSizeThreshold = other.contentSizeThreshold;
36+
this.compressors = other.compressors != null ? new ArrayList<>(other.compressors) : null;
37+
}
38+
39+
/**
40+
* @return the compression content size threshold
41+
*/
42+
public int getContentSizeThreshold() {
43+
return contentSizeThreshold;
44+
}
45+
46+
/**
47+
* Set the compression content size threshold if compression is enabled. This is only applicable for HTTP/1.x response bodies.
48+
* If the response content size in bytes is greater than this threshold, then the response is compressed. Otherwise, it is not compressed.
49+
*
50+
* @param contentSizeThreshold integer greater than or equal to 0.
51+
* @return a reference to this, so the API can be used fluently
52+
*/
53+
public HttpCompressionOptions setContentSizeThreshold(int contentSizeThreshold) {
54+
Arguments.require(contentSizeThreshold >= 0, "compressionContentSizeThreshold must be >= 0");
55+
this.contentSizeThreshold = contentSizeThreshold;
56+
return this;
57+
}
58+
59+
/**
60+
* @return the list of compressor to use
61+
*/
62+
public List<CompressionOptions> getCompressors() {
63+
return compressors;
64+
}
65+
66+
/**
67+
* Add a compressor.
68+
*
69+
* @see #setCompressors(List)
70+
* @return a reference to this, so the API can be used fluently
71+
*/
72+
public HttpCompressionOptions addCompressor(CompressionOptions compressor) {
73+
if (compressors == null) {
74+
compressors = new ArrayList<>();
75+
}
76+
compressors.add(compressor);
77+
return this;
78+
}
79+
80+
/**
81+
* @param compressors the list of compressors
82+
* @return a reference to this, so the API can be used fluently
83+
*/
84+
public HttpCompressionOptions setCompressors(List<CompressionOptions> compressors) {
85+
this.compressors = compressors;
86+
return this;
87+
}
88+
}

vertx-core/src/main/java/io/vertx/core/http/HttpServerOptions.java

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,7 @@ public class HttpServerOptions extends NetServerOptions {
211211

212212
private boolean compressionSupported;
213213
private int compressionLevel;
214-
private int compressionContentSizeThreshold;
215-
private List<CompressionOptions> compressors;
214+
private HttpCompressionOptions compression;
216215
private int maxWebSocketFrameSize;
217216
private int maxWebSocketMessageSize;
218217
private List<String> webSocketSubProtocols;
@@ -261,8 +260,7 @@ public HttpServerOptions(HttpServerOptions other) {
261260
super(other);
262261
this.compressionSupported = other.isCompressionSupported();
263262
this.compressionLevel = other.getCompressionLevel();
264-
this.compressionContentSizeThreshold = other.getCompressionContentSizeThreshold();
265-
this.compressors = other.compressors != null ? new ArrayList<>(other.compressors) : null;
263+
this.compression = other.compression != null ? new HttpCompressionOptions(other.compression) : new HttpCompressionOptions();
266264
this.maxWebSocketFrameSize = other.maxWebSocketFrameSize;
267265
this.maxWebSocketMessageSize = other.maxWebSocketMessageSize;
268266
this.webSocketSubProtocols = other.webSocketSubProtocols != null ? new ArrayList<>(other.webSocketSubProtocols) : null;
@@ -320,8 +318,7 @@ public JsonObject toJson() {
320318
private void init() {
321319
strictThreadMode = DEFAULT_STRICT_THREAD_MODE_STRICT;
322320
compressionSupported = DEFAULT_COMPRESSION_SUPPORTED;
323-
compressionLevel = DEFAULT_COMPRESSION_LEVEL;
324-
compressionContentSizeThreshold = DEFAULT_COMPRESSION_CONTENT_SIZE_THRESHOLD;
321+
compression = new HttpCompressionOptions();
325322
maxWebSocketFrameSize = DEFAULT_MAX_WEBSOCKET_FRAME_SIZE;
326323
maxWebSocketMessageSize = DEFAULT_MAX_WEBSOCKET_MESSAGE_SIZE;
327324
handle100ContinueAutomatically = DEFAULT_HANDLE_100_CONTINE_AUTOMATICALLY;
@@ -572,6 +569,24 @@ public HttpServerOptions setCompressionSupported(boolean compressionSupported) {
572569
return this;
573570
}
574571

572+
/**
573+
* @return the compression configuration
574+
*/
575+
public HttpCompressionOptions getCompression() {
576+
return compression;
577+
}
578+
579+
/**
580+
* Configure the server compression, this overwrites any previously configuration.
581+
*
582+
* @param compression the new configuration
583+
* @return a reference to this, so the API can be used fluently
584+
*/
585+
public HttpServerOptions setCompression(HttpCompressionOptions compression) {
586+
this.compression = compression == null ? new HttpCompressionOptions() : compression;
587+
return this;
588+
}
589+
575590
/**
576591
*
577592
* @return the server gzip/deflate 'compression level' to be used in responses when client and server support is turned on
@@ -580,7 +595,6 @@ public int getCompressionLevel() {
580595
return this.compressionLevel;
581596
}
582597

583-
584598
/**
585599
* This method allows to set the compression level to be used in http1.x/2 response bodies
586600
* when compression support is turned on (@see setCompressionSupported) and the client advertises
@@ -616,7 +630,7 @@ public HttpServerOptions setCompressionLevel(int compressionLevel) {
616630
* @return the compression content size threshold
617631
*/
618632
public int getCompressionContentSizeThreshold() {
619-
return compressionContentSizeThreshold;
633+
return compression.getContentSizeThreshold();
620634
}
621635

622636
/**
@@ -627,16 +641,15 @@ public int getCompressionContentSizeThreshold() {
627641
* @return a reference to this, so the API can be used fluently
628642
*/
629643
public HttpServerOptions setCompressionContentSizeThreshold(int compressionContentSizeThreshold) {
630-
Arguments.require(compressionContentSizeThreshold >= 0, "compressionContentSizeThreshold must be >= 0");
631-
this.compressionContentSizeThreshold = compressionContentSizeThreshold;
644+
compression.setContentSizeThreshold(compressionContentSizeThreshold);
632645
return this;
633646
}
634647

635648
/**
636649
* @return the list of compressor to use
637650
*/
638651
public List<CompressionOptions> getCompressors() {
639-
return compressors;
652+
return compression.getCompressors();
640653
}
641654

642655
/**
@@ -646,10 +659,7 @@ public List<CompressionOptions> getCompressors() {
646659
* @return a reference to this, so the API can be used fluently
647660
*/
648661
public HttpServerOptions addCompressor(CompressionOptions compressor) {
649-
if (compressors == null) {
650-
compressors = new ArrayList<>();
651-
}
652-
compressors.add(compressor);
662+
compression.addCompressor(compressor);
653663
return this;
654664
}
655665

@@ -662,7 +672,7 @@ public HttpServerOptions addCompressor(CompressionOptions compressor) {
662672
* @return a reference to this, so the API can be used fluently
663673
*/
664674
public HttpServerOptions setCompressors(List<CompressionOptions> compressors) {
665-
this.compressors = compressors;
675+
compression.setCompressors(compressors);
666676
return this;
667677
}
668678

vertx-core/src/test/java/io/vertx/test/http/HttpConfig.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ public HttpClientBuilder builder(Vertx vertx) {
7676
public HttpServerConfig forServer() {
7777
HttpServerOptions options = createBaseServerOptions();
7878
return new HttpServerConfig() {
79+
@Override
80+
public HttpServerConfig setDecompressionSupported(boolean supported) {
81+
options.setDecompressionSupported(supported);
82+
return this;
83+
}
84+
@Override
85+
public HttpServerConfig setCompressionSupported(boolean supported) {
86+
options.setCompressionSupported(supported);
87+
return this;
88+
}
89+
@Override
90+
public HttpServerConfig setCompression(HttpCompressionOptions compression) {
91+
options.setCompression(compression);
92+
return this;
93+
}
7994
@Override
8095
public HttpServerConfig setMaxFormBufferedBytes(int maxFormBufferedBytes) {
8196
options.setMaxFormBufferedBytes(maxFormBufferedBytes);

vertx-core/src/test/java/io/vertx/test/http/HttpServerConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package io.vertx.test.http;
22

33
import io.vertx.core.Vertx;
4+
import io.vertx.core.http.HttpCompressionOptions;
45
import io.vertx.core.http.HttpServer;
56

67
import java.time.Duration;
78

89
public interface HttpServerConfig {
910

11+
HttpServerConfig setDecompressionSupported(boolean supported);
12+
HttpServerConfig setCompressionSupported(boolean supported);
13+
HttpServerConfig setCompression(HttpCompressionOptions compression);
1014
HttpServerConfig setMaxFormBufferedBytes(int maxFormBufferedBytes);
1115
HttpServerConfig setMaxFormAttributeSize(int maxSize);
1216
HttpServerConfig setMaxFormFields(int maxFormFields);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package io.vertx.tests.http.compression;
2+
3+
import io.netty.buffer.ByteBuf;
4+
import io.netty.handler.codec.MessageToByteEncoder;
5+
import io.netty.handler.codec.compression.*;
6+
7+
import java.util.function.Supplier;
8+
9+
public class CompressionConfig {
10+
11+
public static CompressionConfig gzip(int level) {
12+
return new CompressionConfig("gzip", () -> new JdkZlibEncoder(ZlibWrapper.GZIP, level),
13+
StandardCompressionOptions.gzip(level, StandardCompressionOptions.gzip().windowBits(), StandardCompressionOptions.gzip().memLevel())) {
14+
@Override
15+
public String toString() {
16+
return "(gzip level:" + level + ")";
17+
}
18+
};
19+
}
20+
21+
public static CompressionConfig brotli() {
22+
return new CompressionConfig("br", BrotliEncoder::new, StandardCompressionOptions.brotli()) {
23+
@Override
24+
public String toString() {
25+
return "(brotli)";
26+
}
27+
};
28+
}
29+
30+
public static CompressionConfig snappy() {
31+
return new CompressionConfig("snappy", SnappyFrameEncoder::new, StandardCompressionOptions.snappy()) {
32+
@Override
33+
public String toString() {
34+
return "(snappy)";
35+
}
36+
};
37+
}
38+
39+
public static CompressionConfig zstd() {
40+
return new CompressionConfig("zstd", ZstdEncoder::new, StandardCompressionOptions.zstd()) {
41+
@Override
42+
public String toString() {
43+
return "(zstd)";
44+
}
45+
};
46+
}
47+
48+
public final String encoding;
49+
public final Supplier<MessageToByteEncoder<ByteBuf>> encoder;
50+
public final CompressionOptions compressor;
51+
52+
public CompressionConfig(String encoding, Supplier<MessageToByteEncoder<ByteBuf>> encoder, CompressionOptions compressor) {
53+
this.encoding = encoding;
54+
this.encoder = encoder;
55+
this.compressor = compressor;
56+
}
57+
}

vertx-core/src/test/java/io/vertx/tests/http/compression/GzipHttpCompressionTestBase.java

Lines changed: 0 additions & 55 deletions
This file was deleted.

vertx-core/src/test/java/io/vertx/tests/http/compression/Http1xBrotliCompressionTest.java

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)