Use native compression for all embedded containers, not just Tomcat
See gh-3296
This commit is contained in:
parent
31a6d53a95
commit
dde194e2b9
|
|
@ -31,6 +31,8 @@ import org.apache.catalina.valves.RemoteIpValve;
|
|||
import org.apache.coyote.AbstractProtocol;
|
||||
import org.apache.coyote.ProtocolHandler;
|
||||
import org.apache.coyote.http11.AbstractHttp11Protocol;
|
||||
import org.springframework.boot.context.embedded.AbstractConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.AbstractConfigurableEmbeddedServletContainer.CompressionProperties;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
|
||||
|
|
@ -99,6 +101,8 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
|
||||
private final Undertow undertow = new Undertow();
|
||||
|
||||
private CompressionProperties compression = new CompressionProperties();
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private JspServlet jspServlet;
|
||||
|
||||
|
|
@ -120,6 +124,10 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
return this.undertow;
|
||||
}
|
||||
|
||||
public CompressionProperties getCompression() {
|
||||
return this.compression;
|
||||
}
|
||||
|
||||
public String getContextPath() {
|
||||
return this.contextPath;
|
||||
}
|
||||
|
|
@ -239,6 +247,10 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
if (getJspServlet() != null) {
|
||||
container.setJspServlet(getJspServlet());
|
||||
}
|
||||
if (container instanceof AbstractConfigurableEmbeddedServletContainer) {
|
||||
((AbstractConfigurableEmbeddedServletContainer) container)
|
||||
.setCompression(getCompression());
|
||||
}
|
||||
if (container instanceof TomcatEmbeddedServletContainerFactory) {
|
||||
getTomcat()
|
||||
.customizeTomcat((TomcatEmbeddedServletContainerFactory) container);
|
||||
|
|
@ -587,7 +599,6 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
|
|||
valve.setSuffix(".log");
|
||||
factory.addContextValves(valve);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Undertow {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
|
@ -105,6 +106,18 @@ public class ServerPropertiesTests {
|
|||
.getInternalProxies());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompressionBinding() throws Exception {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("server.compression.enabled", "true");
|
||||
map.put("server.compression.mimeTypes", "foo/bar");
|
||||
map.put("server.compression.minSize", "228");
|
||||
bindProperties(map);
|
||||
assertTrue(this.properties.getCompression().isEnabled());
|
||||
assertEquals("foo/bar", this.properties.getCompression().getMimeTypes());
|
||||
assertEquals(228, this.properties.getCompression().getMinSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomizeTomcat() throws Exception {
|
||||
ConfigurableEmbeddedServletContainer factory = mock(ConfigurableEmbeddedServletContainer.class);
|
||||
|
|
|
|||
|
|
@ -154,6 +154,11 @@
|
|||
<artifactId>jetty-util</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlets</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-servlet</artifactId>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.util.Arrays;
|
|||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
|
@ -67,6 +68,8 @@ public abstract class AbstractConfigurableEmbeddedServletContainer implements
|
|||
|
||||
private JspServlet jspServlet = new JspServlet();
|
||||
|
||||
private CompressionProperties compression;
|
||||
|
||||
/**
|
||||
* Create a new {@link AbstractConfigurableEmbeddedServletContainer} instance.
|
||||
*/
|
||||
|
|
@ -278,6 +281,14 @@ public abstract class AbstractConfigurableEmbeddedServletContainer implements
|
|||
return this.jspServlet;
|
||||
}
|
||||
|
||||
public CompressionProperties getCompression() {
|
||||
return this.compression;
|
||||
}
|
||||
|
||||
public void setCompression(CompressionProperties compression) {
|
||||
this.compression = compression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that can be used by subclasses wishing to combine the specified
|
||||
* {@link ServletContextInitializer} parameters with those defined in this instance.
|
||||
|
|
@ -306,4 +317,44 @@ public abstract class AbstractConfigurableEmbeddedServletContainer implements
|
|||
.getClassLoader());
|
||||
}
|
||||
|
||||
public static class CompressionProperties {
|
||||
private boolean enabled = false;
|
||||
private String mimeTypes = "text/html,text/xml,text/plain,text/css";
|
||||
private int minSize = 2048;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getMimeTypes() {
|
||||
return mimeTypes;
|
||||
}
|
||||
|
||||
public void setMimeTypes(String mimeTypes) {
|
||||
this.mimeTypes = mimeTypes;
|
||||
}
|
||||
|
||||
public int getMinSize() {
|
||||
return minSize;
|
||||
}
|
||||
|
||||
public void setMinSize(int minSize) {
|
||||
this.minSize = minSize;
|
||||
}
|
||||
|
||||
public List<String> getMimeTypesList() {
|
||||
List<String> mimeTypesList = new ArrayList<String>();
|
||||
StringTokenizer tok = new StringTokenizer(mimeTypes, ",", false);
|
||||
while (tok.hasMoreTokens()) {
|
||||
mimeTypesList.add(tok.nextToken());
|
||||
}
|
||||
return mimeTypesList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.springframework.boot.context.embedded.jetty;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -37,6 +38,7 @@ import org.eclipse.jetty.server.ServerConnector;
|
|||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlet.ServletMapping;
|
||||
|
|
@ -59,6 +61,7 @@ import org.springframework.context.ResourceLoaderAware;
|
|||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -113,6 +116,12 @@ public class JettyEmbeddedServletContainerFactory extends
|
|||
super(contextPath, port);
|
||||
}
|
||||
|
||||
private static final String[] GZIP_HANDLER_CLASSNAMES = new String[] {
|
||||
"org.eclipse.jetty.servlets.gzip.GzipHandler", // Jetty 9.2
|
||||
"org.eclipse.jetty.server.handler.gzip.GzipHandler", // Jetty 9.3
|
||||
"org.eclipse.jetty.server.handler.GzipHandler" // Jetty 8
|
||||
};
|
||||
|
||||
@Override
|
||||
public EmbeddedServletContainer getEmbeddedServletContainer(
|
||||
ServletContextInitializer... initializers) {
|
||||
|
|
@ -120,7 +129,12 @@ public class JettyEmbeddedServletContainerFactory extends
|
|||
int port = (getPort() >= 0 ? getPort() : 0);
|
||||
Server server = new Server(new InetSocketAddress(getAddress(), port));
|
||||
configureWebAppContext(context, initializers);
|
||||
server.setHandler(context);
|
||||
if (getCompression() != null && getCompression().isEnabled()) {
|
||||
setupGzipHandler(context, server);
|
||||
}
|
||||
else {
|
||||
server.setHandler(context);
|
||||
}
|
||||
this.logger.info("Server initialized with port: " + port);
|
||||
if (getSsl() != null && getSsl().isEnabled()) {
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
|
|
@ -135,6 +149,52 @@ public class JettyEmbeddedServletContainerFactory extends
|
|||
return getJettyEmbeddedServletContainer(server);
|
||||
}
|
||||
|
||||
private void setupGzipHandler(JettyEmbeddedWebAppContext context, Server server)
|
||||
throws LinkageError {
|
||||
boolean done = false;
|
||||
for (String gzipHandlerClassName : GZIP_HANDLER_CLASSNAMES) {
|
||||
if (ClassUtils.isPresent(gzipHandlerClassName, null)) {
|
||||
try {
|
||||
Class<?> gzipHandlerClass = ClassUtils.forName(gzipHandlerClassName,
|
||||
null);
|
||||
|
||||
HandlerWrapper gzipHandler = (HandlerWrapper) gzipHandlerClass
|
||||
.newInstance();
|
||||
gzipHandler.setHandler(context);
|
||||
|
||||
Method minGzipSizeMethod = ReflectionUtils.findMethod(
|
||||
gzipHandlerClass, "setMinGzipSize", int.class);
|
||||
minGzipSizeMethod.invoke(gzipHandler, getCompression().getMinSize());
|
||||
|
||||
Method mimeTypesMethod = ReflectionUtils.findMethod(gzipHandlerClass,
|
||||
"setMimeTypes", String.class);
|
||||
if (mimeTypesMethod != null) {
|
||||
// Jetty 8 & Jety 9.2
|
||||
mimeTypesMethod.invoke(gzipHandler, getCompression()
|
||||
.getMimeTypes());
|
||||
}
|
||||
else {
|
||||
// Jetty 9.3
|
||||
mimeTypesMethod = ReflectionUtils.findMethod(gzipHandlerClass,
|
||||
"setIncludedMimeTypes", String[].class);
|
||||
List<String> mimeTypes = getCompression().getMimeTypesList();
|
||||
mimeTypesMethod.invoke(gzipHandler,
|
||||
(Object) mimeTypes.toArray(new String[mimeTypes.size()]));
|
||||
}
|
||||
server.setHandler(gzipHandler);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
throw new IllegalStateException("Jetty GzipHandler is not in classpath");
|
||||
}
|
||||
}
|
||||
|
||||
private SslServerConnectorFactory getSslServerConnectorFactory() {
|
||||
if (ClassUtils.isPresent("org.eclipse.jetty.server.ssl.SslSocketConnector", null)) {
|
||||
return new Jetty8SslServerConnectorFactory();
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ import org.apache.catalina.loader.WebappLoader;
|
|||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.catalina.startup.Tomcat.FixContextListener;
|
||||
import org.apache.coyote.AbstractProtocol;
|
||||
import org.apache.coyote.ProtocolHandler;
|
||||
import org.apache.coyote.http11.AbstractHttp11JsseProtocol;
|
||||
import org.apache.coyote.http11.AbstractHttp11Protocol;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
|
|
@ -255,6 +257,17 @@ public class TomcatEmbeddedServletContainerFactory extends
|
|||
connector.setSecure(true);
|
||||
}
|
||||
|
||||
if (getCompression() != null && getCompression().isEnabled()) {
|
||||
ProtocolHandler handler = connector.getProtocolHandler();
|
||||
if (handler instanceof AbstractHttp11Protocol) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) handler;
|
||||
protocol.setCompression("on");
|
||||
protocol.setCompressionMinSize(getCompression().getMinSize());
|
||||
protocol.setCompressableMimeTypes(getCompression().getMimeTypes());
|
||||
}
|
||||
}
|
||||
|
||||
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
|
||||
customizer.customize(connector);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,17 @@ package org.springframework.boot.context.embedded.undertow;
|
|||
import io.undertow.Handlers;
|
||||
import io.undertow.Undertow;
|
||||
import io.undertow.Undertow.Builder;
|
||||
import io.undertow.attribute.ConstantExchangeAttribute;
|
||||
import io.undertow.attribute.ExchangeAttribute;
|
||||
import io.undertow.attribute.ResponseHeaderAttribute;
|
||||
import io.undertow.predicate.Predicate;
|
||||
import io.undertow.predicate.Predicates;
|
||||
import io.undertow.server.HttpHandler;
|
||||
import io.undertow.server.handlers.encoding.ContentEncodingRepository;
|
||||
import io.undertow.server.handlers.encoding.EncodingHandler;
|
||||
import io.undertow.server.handlers.encoding.GzipEncodingProvider;
|
||||
import io.undertow.servlet.api.DeploymentManager;
|
||||
import io.undertow.util.HttpString;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.ServerSocket;
|
||||
|
|
@ -31,8 +40,10 @@ import javax.servlet.ServletException;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.boot.context.embedded.AbstractConfigurableEmbeddedServletContainer.CompressionProperties;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -59,16 +70,20 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine
|
|||
|
||||
private final boolean autoStart;
|
||||
|
||||
private final CompressionProperties compression;
|
||||
|
||||
private Undertow undertow;
|
||||
|
||||
private boolean started = false;
|
||||
|
||||
public UndertowEmbeddedServletContainer(Builder builder, DeploymentManager manager,
|
||||
String contextPath, int port, boolean autoStart) {
|
||||
String contextPath, int port, boolean autoStart,
|
||||
CompressionProperties compression) {
|
||||
this.builder = builder;
|
||||
this.manager = manager;
|
||||
this.contextPath = contextPath;
|
||||
this.autoStart = autoStart;
|
||||
this.compression = compression;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -98,6 +113,29 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine
|
|||
}
|
||||
|
||||
private HttpHandler getContextHandler(HttpHandler servletHandler) {
|
||||
if (compression != null && compression.isEnabled()) {
|
||||
ContentEncodingRepository encodingRepository = new ContentEncodingRepository();
|
||||
|
||||
List<String> mimeTypes = compression.getMimeTypesList();
|
||||
Predicate[] mimePredicates = new Predicate[mimeTypes.size()];
|
||||
ResponseHeaderAttribute mimeHeader = new ResponseHeaderAttribute(
|
||||
new HttpString(HttpHeaders.CONTENT_TYPE));
|
||||
for (int i = 0; i < mimeTypes.size(); i++) {
|
||||
mimePredicates[i] = Predicates.equals(new ExchangeAttribute[] {
|
||||
mimeHeader, new ConstantExchangeAttribute(mimeTypes.get(i)) });
|
||||
|
||||
}
|
||||
|
||||
Predicate mimeAndSizePredicate = Predicates.and(
|
||||
Predicates.maxContentSize(compression.getMinSize()),
|
||||
Predicates.or(mimePredicates));
|
||||
|
||||
encodingRepository.addEncodingHandler("gzip", new GzipEncodingProvider(), 50,
|
||||
mimeAndSizePredicate);
|
||||
servletHandler = new EncodingHandler(encodingRepository)
|
||||
.setNext(servletHandler);
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(this.contextPath)) {
|
||||
return servletHandler;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ public class UndertowEmbeddedServletContainerFactory extends
|
|||
int port = getPort();
|
||||
Builder builder = createBuilder(port);
|
||||
return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(),
|
||||
port, port >= 0);
|
||||
port, port >= 0, getCompression());
|
||||
}
|
||||
|
||||
private Builder createBuilder(int port) {
|
||||
|
|
@ -470,7 +470,7 @@ public class UndertowEmbeddedServletContainerFactory extends
|
|||
protected UndertowEmbeddedServletContainer getUndertowEmbeddedServletContainer(
|
||||
Builder builder, DeploymentManager manager, int port) {
|
||||
return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(),
|
||||
port, port >= 0);
|
||||
port, port >= 0, getCompression());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.io.File;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
|
|
@ -27,6 +28,8 @@ import java.security.KeyStore;
|
|||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.servlet.GenericServlet;
|
||||
|
|
@ -36,8 +39,10 @@ import javax.servlet.ServletRequest;
|
|||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.InputStreamFactory;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.ssl.SSLContextBuilder;
|
||||
import org.junit.After;
|
||||
|
|
@ -46,6 +51,7 @@ import org.junit.Test;
|
|||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.mockito.InOrder;
|
||||
import org.springframework.boot.context.embedded.AbstractConfigurableEmbeddedServletContainer.CompressionProperties;
|
||||
import org.springframework.boot.context.embedded.Ssl.ClientAuth;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
|
@ -58,6 +64,7 @@ import org.springframework.util.SocketUtils;
|
|||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
|
@ -65,7 +72,9 @@ import static org.hamcrest.Matchers.lessThan;
|
|||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
|
@ -520,6 +529,79 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
|||
assertThat(getFactory().getSessionTimeout(), equalTo(30 * 60));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compression() throws Exception {
|
||||
assertTrue(internalTestCompression(10000, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noCompressionForSmallResponse() throws Exception {
|
||||
assertFalse(internalTestCompression(100, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noCompressionForMimeType() throws Exception {
|
||||
assertFalse(internalTestCompression(10000, "text/html,text/xml,text/css"));
|
||||
}
|
||||
|
||||
protected String setupFactoryForCompression(int contentSize, String mimeTypes)
|
||||
throws Exception {
|
||||
char[] chars = new char[contentSize];
|
||||
Arrays.fill(chars, 'F');
|
||||
String testContent = new String(chars);
|
||||
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
|
||||
FileCopyUtils.copy(testContent,
|
||||
new FileWriter(this.temporaryFolder.newFile("test.txt")));
|
||||
factory.setDocumentRoot(this.temporaryFolder.getRoot());
|
||||
CompressionProperties compression = new CompressionProperties();
|
||||
compression.setEnabled(true);
|
||||
if (mimeTypes != null) {
|
||||
compression.setMimeTypes(mimeTypes);
|
||||
}
|
||||
factory.setCompression(compression);
|
||||
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
this.container.start();
|
||||
return testContent;
|
||||
}
|
||||
|
||||
private boolean internalTestCompression(int contentSize, String mimeTypes)
|
||||
throws Exception {
|
||||
String testContent = setupFactoryForCompression(contentSize, mimeTypes);
|
||||
|
||||
class TestGzipInputStreamFactory implements InputStreamFactory {
|
||||
|
||||
final AtomicBoolean requested = new AtomicBoolean(false);
|
||||
|
||||
@Override
|
||||
public InputStream create(InputStream instream) throws IOException {
|
||||
if (requested.get()) {
|
||||
throw new IllegalStateException(
|
||||
"On deflated InputStream already requested");
|
||||
}
|
||||
requested.set(true);
|
||||
return new GZIPInputStream(instream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TestGzipInputStreamFactory gzipTestInputStreamFactory = new TestGzipInputStreamFactory();
|
||||
|
||||
String response = getResponse(
|
||||
getLocalUrl("/test.txt"),
|
||||
new HttpComponentsClientHttpRequestFactory(HttpClientBuilder
|
||||
.create()
|
||||
.setContentDecoderRegistry(
|
||||
singletonMap("gzip",
|
||||
(InputStreamFactory) gzipTestInputStreamFactory))
|
||||
.build()));
|
||||
assertThat(response, equalTo(testContent));
|
||||
boolean wasCompressionUsed = gzipTestInputStreamFactory.requested.get();
|
||||
return wasCompressionUsed;
|
||||
}
|
||||
|
||||
private void addTestTxtFile(AbstractEmbeddedServletContainerFactory factory)
|
||||
throws IOException {
|
||||
FileCopyUtils.copy("test",
|
||||
|
|
|
|||
|
|
@ -16,11 +16,17 @@
|
|||
|
||||
package org.springframework.boot.context.embedded.jetty;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
|
|
@ -32,8 +38,12 @@ import org.eclipse.jetty.webapp.Configuration;
|
|||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests;
|
||||
import org.springframework.boot.context.embedded.ServletRegistrationBean;
|
||||
import org.springframework.boot.context.embedded.Ssl;
|
||||
import org.springframework.boot.context.embedded.AbstractConfigurableEmbeddedServletContainer.CompressionProperties;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
|
@ -173,6 +183,38 @@ public class JettyEmbeddedServletContainerFactoryTests extends
|
|||
assertThat(getJspServlet().getInitParameters(), is(equalTo(initParameters)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("serial")
|
||||
// work-around for Jetty issue - https://bugs.eclipse.org/bugs/show_bug.cgi?id=470646
|
||||
protected String setupFactoryForCompression(final int contentSize, String mimeTypes)
|
||||
throws Exception {
|
||||
char[] chars = new char[contentSize];
|
||||
Arrays.fill(chars, 'F');
|
||||
final String testContent = new String(chars);
|
||||
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
|
||||
CompressionProperties compression = new CompressionProperties();
|
||||
compression.setEnabled(true);
|
||||
if (mimeTypes != null) {
|
||||
compression.setMimeTypes(mimeTypes);
|
||||
}
|
||||
factory.setCompression(compression);
|
||||
|
||||
this.container = factory.getEmbeddedServletContainer(new ServletRegistrationBean(
|
||||
new HttpServlet() {
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
resp.setContentLength(contentSize);
|
||||
resp.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain");
|
||||
resp.getWriter().print(testContent);
|
||||
}
|
||||
}, "/test.txt"));
|
||||
this.container.start();
|
||||
return testContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServletHolder getJspServlet() {
|
||||
WebAppContext context = (WebAppContext) ((JettyEmbeddedServletContainer) this.container)
|
||||
|
|
|
|||
Loading…
Reference in New Issue