This is an automated email from the ASF dual-hosted git repository.
brusdev pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/artemis.git
The following commit(s) were added to refs/heads/main by this push:
new 2df59c5b8f ARTEMIS-5833 support compression for HTTP responses
2df59c5b8f is described below
commit 2df59c5b8f9fdee8cc171df393731e0ff3bca3df
Author: Justin Bertram <[email protected]>
AuthorDate: Fri Dec 19 15:17:51 2025 -0600
ARTEMIS-5833 support compression for HTTP responses
---
.../apache/activemq/artemis/dto/WebServerDTO.java | 6 +++
artemis-web/pom.xml | 8 +++
.../artemis/component/WebServerComponent.java | 22 +++++++-
.../activemq/cli/test/WebServerComponentTest.java | 59 ++++++++++++++++++++++
.../webapps/WebServerComponentCompressionTest.txt | 1 +
docs/user-manual/web-server.adoc | 9 ++++
6 files changed, 103 insertions(+), 2 deletions(-)
diff --git
a/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/WebServerDTO.java
b/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/WebServerDTO.java
index b118c708ad..9a122e7512 100644
---
a/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/WebServerDTO.java
+++
b/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/WebServerDTO.java
@@ -113,6 +113,12 @@ public class WebServerDTO extends ComponentDTO {
@XmlAttribute
public Integer maxResponseHeaderSize;
+ @XmlAttribute
+ public Boolean compressionEnabled;
+
+ @XmlAttribute
+ public Integer compressionLevel;
+
public String getPath() {
return path;
}
diff --git a/artemis-web/pom.xml b/artemis-web/pom.xml
index 7459b95046..2f887519b9 100644
--- a/artemis-web/pom.xml
+++ b/artemis-web/pom.xml
@@ -102,6 +102,14 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-java-server</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.compression</groupId>
+ <artifactId>jetty-compression-server</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.compression</groupId>
+ <artifactId>jetty-compression-gzip</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.artemis</groupId>
<artifactId>artemis-server</artifactId>
diff --git
a/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
b/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
index 316b0e3120..c5af6026bd 100644
---
a/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
+++
b/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
@@ -57,6 +57,11 @@ import org.apache.activemq.artemis.utils.ClassloadingUtil;
import org.apache.activemq.artemis.utils.PemConfigUtil;
import org.apache.activemq.artemis.utils.sm.SecurityManagerShim;
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
+import org.eclipse.jetty.compression.Compression;
+import org.eclipse.jetty.compression.EncoderConfig;
+import org.eclipse.jetty.compression.gzip.GzipCompression;
+import org.eclipse.jetty.compression.gzip.GzipEncoderConfig;
+import org.eclipse.jetty.compression.server.CompressionHandler;
import org.eclipse.jetty.ee9.security.DefaultAuthenticatorFactory;
import org.eclipse.jetty.ee9.servlet.FilterHolder;
import org.eclipse.jetty.ee9.webapp.WebAppContext;
@@ -149,6 +154,21 @@ public class WebServerComponent implements
ExternalComponent, WebServerComponent
Scheduler scheduler = new
ScheduledExecutorScheduler("activemq-web-scheduled", false);
server = new Server(threadPool, scheduler, null);
handlers = new Handler.Sequence();
+ if (webServerConfig.compressionEnabled != null &&
webServerConfig.compressionEnabled) {
+ int compressionLevel =
Objects.requireNonNullElse(webServerConfig.compressionLevel, 6);
+ logger.debug("embedded web server is using GZIP compression level
{}", compressionLevel);
+ EncoderConfig encoderConfig = new GzipEncoderConfig();
+ encoderConfig.setCompressionLevel(compressionLevel);
+ Compression compression = new GzipCompression();
+ compression.setDefaultEncoderConfig(encoderConfig);
+ CompressionHandler compressionHandler = new CompressionHandler();
+ compressionHandler.putCompression(compression);
+ compressionHandler.setHandler(handlers);
+ server.setHandler(compressionHandler);
+ } else {
+ server.setHandler(handlers);
+ }
+
HttpConfiguration httpConfiguration = new HttpConfiguration();
@@ -253,8 +273,6 @@ public class WebServerComponent implements
ExternalComponent, WebServerComponent
handlers.addHandler(defaultHandler); // this should be last
- server.setHandler(handlers);
-
server.start();
printStatus(bindings);
diff --git
a/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerComponentTest.java
b/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerComponentTest.java
index 1f56dad6bd..a6134483ce 100644
---
a/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerComponentTest.java
+++
b/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerComponentTest.java
@@ -65,6 +65,7 @@ import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaderNames;
+import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpRequest;
@@ -202,6 +203,62 @@ public class WebServerComponentTest extends
ArtemisTestCase {
assertFalse(webServerComponent.isStarted());
}
+ @Test
+ public void testCompressionEnabled() throws Exception {
+ testCompression(true);
+ }
+
+ @Test
+ public void testCompressionDisabled() throws Exception {
+ testCompression(false);
+ }
+
+ private void testCompression(boolean compressionEnabled) throws Exception {
+ final String encoding = "gzip";
+
+ BindingDTO bindingDTO = new BindingDTO();
+ bindingDTO.uri = "http://localhost:0";
+ WebServerDTO webServerDTO = new WebServerDTO();
+ webServerDTO.setBindings(Collections.singletonList(bindingDTO));
+ webServerDTO.path = "webapps";
+ webServerDTO.webContentEnabled = true;
+ webServerDTO.compressionEnabled = compressionEnabled;
+ WebServerComponent webServerComponent = new WebServerComponent();
+ assertFalse(webServerComponent.isStarted());
+ webServerComponent.configure(webServerDTO, "src/test/resources/",
"src/test/resources/");
+ testedComponents.add(webServerComponent);
+ webServerComponent.start();
+ final int port = webServerComponent.getPort();
+ // Make the connection attempt.
+ CountDownLatch latch = new CountDownLatch(1);
+ final ClientHandler clientHandler = new ClientHandler(latch);
+ Channel ch = getChannel(port, clientHandler);
+
+ // this file is different from the other tests because it has to be
above a certain size in order to be compressed
+ URI uri = new
URI("http://localhost/WebServerComponentCompressionTest.txt");
+ // Prepare the HTTP request.
+ HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1,
HttpMethod.GET, uri.getRawPath());
+ request.headers().set(HttpHeaderNames.HOST, "localhost");
+ request.headers().set(HttpHeaderNames.ACCEPT_ENCODING, encoding);
+
+ // Send the HTTP request.
+ ch.writeAndFlush(request);
+ assertTrue(latch.await(5, TimeUnit.SECONDS));
+ String contentEncoding =
clientHandler.headers.get(HttpHeaderNames.CONTENT_ENCODING);
+ if (compressionEnabled) {
+ assertEquals(encoding, contentEncoding);
+ } else {
+ assertNull(contentEncoding);
+ }
+
+ // Wait for the server to close the connection.
+ ch.close();
+ ch.eventLoop().shutdownNow();
+ assertTrue(webServerComponent.isStarted());
+ webServerComponent.stop(true);
+ assertFalse(webServerComponent.isStarted());
+ }
+
@Test
public void testThreadPool() throws Exception {
BindingDTO bindingDTO = new BindingDTO();
@@ -1133,6 +1190,7 @@ public class WebServerComponentTest extends
ArtemisTestCase {
private CountDownLatch latch;
private StringBuilder body = new StringBuilder();
private String serverHeader;
+ private HttpHeaders headers;
ClientHandler(CountDownLatch latch) {
this.latch = latch;
@@ -1141,6 +1199,7 @@ public class WebServerComponentTest extends
ArtemisTestCase {
@Override
public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) {
if (msg instanceof HttpResponse response) {
+ headers = response.headers();
serverHeader = response.headers().get("Server");
} else if (msg instanceof HttpContent content) {
body.append(content.content().toString(CharsetUtil.UTF_8));
diff --git
a/artemis-web/src/test/resources/webapps/WebServerComponentCompressionTest.txt
b/artemis-web/src/test/resources/webapps/WebServerComponentCompressionTest.txt
new file mode 100644
index 0000000000..fd4f971ab3
--- /dev/null
+++
b/artemis-web/src/test/resources/webapps/WebServerComponentCompressionTest.txt
@@ -0,0 +1 @@
+0123456789012345678901234567890123456789
\ No newline at end of file
diff --git a/docs/user-manual/web-server.adoc b/docs/user-manual/web-server.adoc
index 9f648e8fa2..b71aba496e 100644
--- a/docs/user-manual/web-server.adoc
+++ b/docs/user-manual/web-server.adoc
@@ -34,6 +34,15 @@ The location to redirect the requests with the root target.
webContentEnabled::
Whether or not the content included in the web folder of the home and the
instance directories is accessible.
Default is `false`.
+compressionEnabled::
+Whether to compress HTTP responses.
+Uses `gzip` encoding for maximum compatibility.
+This will impact any client communicating with the embedded web server
including the web console and consumers of xref:metrics.adoc#metrics[metrics]
(e.g. Prometheus) assuming they set the `Accept-Encoding` header to `gzip` in
their HTTP requests.
+Default is `false`.
+compressionLevel::
+The level of compression for HTTP responses.
+Only valid if `compressionEnabled` is `true`.
+Default is `6`. Must be between `0` and `9` inclusive.
maxThreads::
The maximum number of threads the embedded web server can create to service
HTTP requests.
Default is `200`.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]