Skip to content

Commit

Permalink
Delegate compression to servlet container (#390)
Browse files Browse the repository at this point in the history
  • Loading branch information
basil committed Jun 14, 2024
1 parent d48037e commit aa80ffb
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ To run locally exploded web archive:
"^.*_anon_.*$"
--controlPort = set the shutdown/control port. -1 to disable, Default disabled

--compression = set the compression scheme (gzip or none to disable compression). Default is gzip.
--sessionTimeout = set the http session timeout value in minutes. Default to what webapp specifies, and then to 60 minutes
--sessionEviction = set the session eviction timeout for idle sessions in seconds. Default value is 180. -1 never evict, 0 evict on exit
--mimeTypes=ARG = define additional MIME type mappings. ARG would be EXT=MIMETYPE:EXT=MIMETYPE:...
Expand Down
17 changes: 16 additions & 1 deletion src/main/java/winstone/HostConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
import winstone.cmdline.CompressionScheme;
import winstone.cmdline.Option;

/**
Expand Down Expand Up @@ -103,7 +105,20 @@ public HostConfiguration(Server server, String hostname, ClassLoader commonLibCL
}
}

server.setHandler(handler);
CompressionScheme compressionScheme = Option.COMPRESSION.get(this.args);
switch (compressionScheme) {

Check warning on line 109 in src/main/java/winstone/HostConfiguration.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 109 is only partially covered, one branch is missing
case GZIP:
GzipHandler gzipHandler = new GzipHandler();
gzipHandler.setHandler(handler);
server.setHandler(gzipHandler);
break;
case NONE:
server.setHandler(handler);
break;
default:
throw new IllegalArgumentException("Unexpected compression scheme: " + compressionScheme);

Check warning on line 119 in src/main/java/winstone/HostConfiguration.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 119 is not covered by tests
}

Logger.log(
Level.FINER,
Launcher.RESOURCES,
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/winstone/cmdline/CompressionScheme.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package winstone.cmdline;

/**
* The compression schemes supported by the server. In the future, this list may be expanded as support for additional
* compression schemes is added to Jetty upstream.
*/
public enum CompressionScheme {
GZIP,
NONE,
}
26 changes: 26 additions & 0 deletions src/main/java/winstone/cmdline/Option.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public static List<Option<?>> all(Class<?> clazz) {
public static final OInt JETTY_ACCEPTORS = integer("jettyAcceptorsCount", -1);
public static final OInt JETTY_SELECTORS = integer("jettySelectorsCount", 0);

public static final OCompression COMPRESSION = new OCompression("compression", CompressionScheme.GZIP);
public static final OString MIME_TYPES = string("mimeTypes");
public static final OInt MAX_PARAM_COUNT = integer("maxParamCount", -1);
public static final OBoolean USAGE = bool("usage", false);
Expand Down Expand Up @@ -307,6 +308,31 @@ public <T> Class<? extends T> get(Map<String, String> args, Class<T> expectedTyp
}
}

public static class OCompression extends Option<CompressionScheme> {
public OCompression(String name, CompressionScheme defaultValue) {
super(name, CompressionScheme.class, defaultValue);
}

public CompressionScheme get(Map<String, String> args) {
return get(args, defaultValue);
}

public CompressionScheme get(Map<String, String> args, CompressionScheme defaultValue) {
String v = args.get(name);
CompressionScheme compressionScheme;
if (v == null) {
compressionScheme = defaultValue;
} else if (v.equalsIgnoreCase("gzip")) {
compressionScheme = CompressionScheme.GZIP;
} else if (v.equalsIgnoreCase("none")) {

Check warning on line 327 in src/main/java/winstone/cmdline/Option.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 327 is only partially covered, one branch is missing
compressionScheme = CompressionScheme.NONE;
} else {
throw new IllegalArgumentException("Unexpected compression scheme: " + v);

Check warning on line 330 in src/main/java/winstone/cmdline/Option.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 330 is not covered by tests
}
return compressionScheme;
}
}

// static {
// String[] protocols = {"http","https"};
// for (int i=0; i<protocols.length; i++) {
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/winstone/LocalStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Launcher.UsageInstructions.Options=\
\ "^.*_NULL_.*$", \n\
\ "^.*_anon_.*$" \n\
\ --controlPort = set the shutdown/control port. -1 to disable, Default disabled\n\n\
\ --compression = set the compression scheme (gzip or none to disable compression). Default is gzip.\n\
\ --sessionTimeout = set the http session timeout value in minutes. Default to what webapp specifies, and then to 60 minutes\n\
\ --sessionEviction = set the session eviction timeout for idle sessions in seconds. Default value is 180. -1 never evict, 0 evict on exit\n\
\ --mimeTypes=ARG = define additional MIME type mappings. ARG would be EXT=MIMETYPE:EXT=MIMETYPE:...\n\
Expand Down
64 changes: 64 additions & 0 deletions src/test/java/winstone/LauncherTest.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,85 @@
package winstone;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import org.eclipse.jetty.server.ServerConnector;
import org.junit.Test;

/**
* @author Kohsuke Kawaguchi
*/
public class LauncherTest extends AbstractWinstoneTest {
@Test
public void implicitGzip() throws Exception {
Map<String, String> args = new HashMap<>();
args.put("warfile", "target/test-classes/test.war");
args.put("prefix", "/");
args.put("httpPort", "0");
winstone = new Launcher(args);
verifyGzip(true);
}

@Test
public void explicitGzip() throws Exception {
Map<String, String> args = new HashMap<>();
args.put("warfile", "target/test-classes/test.war");
args.put("prefix", "/");
args.put("httpPort", "0");
args.put("compression", "gzip");
winstone = new Launcher(args);
verifyGzip(true);
}

@Test
public void noCompression() throws Exception {
Map<String, String> args = new HashMap<>();
args.put("warfile", "target/test-classes/test.war");
args.put("prefix", "/");
args.put("httpPort", "0");
args.put("compression", "none");
winstone = new Launcher(args);
verifyGzip(false);
}

private void verifyGzip(boolean gzip) throws Exception {
int port = ((ServerConnector) winstone.server.getConnectors()[0]).getLocalPort();
HttpRequest request = HttpRequest.newBuilder(new URI("http://127.0.0.2:" + port + "/lipsum.txt"))
.GET()
.header("Accept-Encoding", "gzip")
.build();
HttpResponse<InputStream> response =
HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofInputStream());
assertEquals(HttpURLConnection.HTTP_OK, response.statusCode());
assertEquals("text/plain", response.headers().firstValue("Content-Type").orElseThrow());
InputStream is;
if (gzip) {
assertEquals(
"gzip", response.headers().firstValue("Content-Encoding").orElseThrow());
is = new GZIPInputStream(response.body());
} else {
assertFalse(response.headers().firstValue("Content-Encoding").isPresent());
is = response.body();
}
try {
assertThat(new String(is.readAllBytes(), StandardCharsets.UTF_8), startsWith("Lorem ipsum dolor sit amet"));
} finally {
is.close();
}
}

@Test
public void mimeType() throws Exception {
Map<String, String> args = new HashMap<>();
Expand Down
9 changes: 9 additions & 0 deletions src/testwebapp/lipsum.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In tristique vehicula bibendum. Aenean ut ligula vel risus suscipit hendrerit. Ut eu nibh quis purus bibendum semper nec non nibh. Mauris a sapien vel arcu lobortis interdum. Proin eget elit accumsan, aliquet lacus pharetra, pulvinar massa. Nullam mauris urna, venenatis at dolor at, vulputate consequat turpis. Aenean tempus dignissim pretium. Pellentesque lobortis tortor ut tristique sagittis. Suspendisse porttitor facilisis leo ac maximus. Sed dapibus metus pulvinar, aliquam leo ut, finibus odio.

Nunc tristique ligula ac porttitor bibendum. Maecenas molestie sagittis dui ac molestie. Nullam et est ex. Nullam et nunc interdum, congue risus quis, viverra neque. In efficitur, mauris ac porta congue, tellus lacus mattis massa, eu pulvinar magna ex non lacus. Proin odio libero, placerat eget neque ut, tristique dignissim eros. Sed elementum feugiat efficitur. Nulla sit amet porta nibh. Vivamus placerat bibendum risus sit amet blandit. Aliquam erat volutpat. Cras orci tellus, posuere eget nunc non, elementum consectetur lacus. Nullam at hendrerit neque.

Pellentesque non interdum est, vitae volutpat arcu. Mauris imperdiet elit sed sodales egestas. Curabitur viverra quis ante in convallis. In feugiat, est eget suscipit mollis, ante ipsum scelerisque ante, ac blandit urna augue non ex. Nam vel elit vel ante gravida dignissim. Duis quis viverra urna. Phasellus ultrices, nulla nec mollis dictum, nulla tortor gravida lorem, id maximus lorem nunc eget nisl. Nulla condimentum ligula massa, id ultrices enim ultrices in. Aliquam rutrum scelerisque lacus non accumsan. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam erat volutpat. In nec congue elit, vel mollis diam. Donec sed erat a massa elementum interdum aliquet at risus. Nulla non euismod eros, porta imperdiet ante.

Aenean lectus est, maximus sed lectus nec, vehicula tincidunt velit. Donec vel ligula eget mi aliquam cursus. Proin laoreet dui eu sapien feugiat facilisis. Praesent nec est id diam pulvinar efficitur. Duis nec facilisis nisl, nec cursus nulla. Nulla lacinia felis ut euismod porta. Curabitur porta sem nec dui posuere, eget vestibulum enim euismod. Duis at ultrices nulla, ullamcorper scelerisque libero. Mauris vel auctor justo, imperdiet fermentum nunc. Integer nec eleifend ex.

Aliquam consectetur tincidunt scelerisque. Nullam fermentum blandit lacus. Quisque aliquam venenatis fringilla. Sed at ultricies lectus. Donec arcu mi, dictum eu sem et, mattis malesuada ligula. Donec facilisis est non est porttitor, id ultrices turpis sollicitudin. In eleifend urna sed justo lobortis tincidunt. Phasellus feugiat venenatis elit vel varius. Aenean lorem erat, iaculis sit amet tincidunt ac, volutpat at ipsum. Donec eleifend ipsum dignissim orci iaculis, nec condimentum nisl lacinia. Donec nec felis in erat finibus consequat.

0 comments on commit aa80ffb

Please sign in to comment.