Skip to content

[WIP] Jetty HTTP2 Support #10041

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.boot.web.server.Compression;
import org.springframework.boot.web.server.Http2;
import org.springframework.boot.web.server.Ssl;
import org.springframework.boot.web.servlet.server.Jsp;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -102,6 +103,9 @@ public class ServerProperties {
@NestedConfigurationProperty
private Compression compression = new Compression();

@NestedConfigurationProperty
private Http2 http2;

private Servlet servlet = new Servlet();

private final Tomcat tomcat = new Tomcat();
Expand Down Expand Up @@ -210,6 +214,14 @@ public Undertow getUndertow() {
return this.undertow;
}

public Http2 getHttp2() {
return this.http2;
}

public void setHttp2(Http2 http2) {
this.http2 = http2;
}

/**
* Servlet properties.
*/
Expand Down Expand Up @@ -907,6 +919,11 @@ public static class Jetty {
*/
private Integer selectors;

/**
* Dump jetty configuration in the logs after starting.
*/
private boolean dumpAfterStart = false;

public Accesslog getAccesslog() {
return this.accesslog;
}
Expand Down Expand Up @@ -935,6 +952,16 @@ public void setSelectors(Integer selectors) {
this.selectors = selectors;
}

public boolean isDumpAfterStart() {
return this.dumpAfterStart;
}

public void setDumpAfterStart(boolean dumpAfterStart) {
this.dumpAfterStart = dumpAfterStart;
}



/**
* Jetty access log properties.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ public void customize(ConfigurableServletWebServerFactory factory) {
if (this.serverProperties.getSsl() != null) {
factory.setSsl(this.serverProperties.getSsl());
}
if (this.serverProperties.getHttp2() != null) {
factory.setHttp2(this.serverProperties.getHttp2());
}
if (this.serverProperties.getServlet() != null) {
factory.setJsp(this.serverProperties.getServlet().getJsp());
}
Expand Down Expand Up @@ -480,6 +483,8 @@ public static void customizeJetty(final ServerProperties serverProperties,
if (jettyProperties.getAccesslog().isEnabled()) {
customizeAccessLog(factory, jettyProperties.getAccesslog());
}

factory.setDumpAfterStart(jettyProperties.isDumpAfterStart());
}

private static void customizeConnectionTimeout(
Expand Down
11 changes: 11 additions & 0 deletions spring-boot-dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
<jersey.version>2.25.1</jersey.version>
<jest.version>5.3.2</jest.version>
<jetty.version>9.4.6.v20170531</jetty.version>
<alpn.api.version>1.1.3.v20160715</alpn.api.version>
<jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.version>
<jetty-el.version>8.5.9.1</jetty-el.version>
<jmustache.version>1.13</jmustache.version>
Expand Down Expand Up @@ -1577,6 +1578,16 @@
<artifactId>http2-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.alpn</groupId>
<artifactId>alpn-api</artifactId>
<version>${alpn.api.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.servlet.jsp</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ content into your application; rather pick only the properties that you need.
server.error.path=/error # Path of the error controller.
server.error.whitelabel.enabled=true # Enable the default error page displayed in browsers in case of a server error.
server.jetty.acceptors= # Number of acceptor threads to use.
server.jetty.dumpAfterStart= false # log all the Jetty configuration in the logs after start
server.jetty.accesslog.append=false # Append to log.
server.jetty.accesslog.date-format=dd/MMM/yyyy:HH:mm:ss Z # Timestamp format of the request log.
server.jetty.accesslog.enabled=false # Enable access log.
Expand Down
16 changes: 16 additions & 0 deletions spring-boot-starters/spring-boot-starter-jetty/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-hpack</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.alpn</groupId>
<artifactId>alpn-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
Expand Down
20 changes: 20 additions & 0 deletions spring-boot/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,26 @@
<artifactId>jetty-webapp</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-hpack</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-server</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.alpn</groupId>
<artifactId>alpn-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,21 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http2.HTTP2Cipher;
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
Expand Down Expand Up @@ -122,6 +127,11 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
*/
private int selectors = -1;

/**
* Dump jetty configuration in the logs after starting.
*/
private boolean dumpAfterStart = false;

private List<JettyServerCustomizer> jettyServerCustomizers = new ArrayList<>();

private ResourceLoader resourceLoader;
Expand Down Expand Up @@ -176,12 +186,22 @@ public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.useForwardHeaders) {
new ForwardHeadersCustomizer().customize(server);
}
if (getHttp2() != null && getHttp2().isEnabled()) {
SslContextFactory sslContextFactory = null;
if (getHttp2().getSsl() != null && getHttp2().getSsl().isEnabled()) {
sslContextFactory = new SslContextFactory();
configureSsl(sslContextFactory, getHttp2().getSsl());
}
AbstractConnector connector = createHttp2Connector(server, sslContextFactory);
server.setConnectors(new Connector[] { connector });
}
return getJettyWebServer(server);
}

private Server createServer(InetSocketAddress address) {
Server server = new Server(getThreadPool());
server.setConnectors(new Connector[] { createConnector(address, server) });
server.setDumpAfterStart(this.dumpAfterStart);
return server;
}

Expand Down Expand Up @@ -213,6 +233,43 @@ private AbstractConnector createSslConnector(Server server,
return serverConnector;
}

private AbstractConnector createHttp2Connector(Server server, SslContextFactory sslContextFactory) {

if (sslContextFactory != null) {
sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR);
}
// HTTPS Configuration
HttpConfiguration https_config = new HttpConfiguration();
https_config.setSecureScheme("https");
https_config.setSecurePort(getHttp2().getPort());
https_config.addCustomizer(new SecureRequestCustomizer());

// HTTP/2 Connection Factory
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(https_config);
NegotiatingServerConnectionFactory.checkProtocolNegotiationAvailable();
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
alpn.setDefaultProtocol("h2");

// HTTP/2 Connector
ServerConnector http2Connector = null;
if (sslContextFactory != null) {
// SSL Connection Factory
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol());
http2Connector = new ServerConnector(server, ssl, alpn, h2, new HttpConnectionFactory(https_config));
}
else {
http2Connector = new ServerConnector(server, alpn, h2, new HttpConnectionFactory(https_config));
}


http2Connector.setPort(getHttp2().getPort());
//?
//http2Connector.setHost(getHttp2().getAddress().getHostName());

ALPN.debug = getHttp2().getAlpnDebug();
return http2Connector;
}

private Handler addHandlerWrappers(Handler handler) {
if (getCompression() != null && getCompression().getEnabled()) {
handler = applyWrapper(handler, createGzipHandler());
Expand Down Expand Up @@ -578,6 +635,14 @@ public void setSelectors(int selectors) {
this.selectors = selectors;
}

/**
* To dump the Jetty configuration in the logs.
* @param dumpAfterStart <code>true</code> to dump configuration
*/
public void setDumpAfterStart(boolean dumpAfterStart) {
this.dumpAfterStart = dumpAfterStart;
}

/**
* Sets {@link JettyServerCustomizer}s that will be applied to the {@link Server}
* before it is started. Calling this method will replace any existing customizers.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public class AbstractConfigurableWebServerFactory

private Ssl ssl;

private Http2 http2;

private SslStoreProvider sslStoreProvider;

private Compression compression;
Expand Down Expand Up @@ -152,6 +154,15 @@ public void setServerHeader(String serverHeader) {
this.serverHeader = serverHeader;
}

@Override
public void setHttp2(Http2 http2) {
this.http2 = http2;
}

public Http2 getHttp2() {
return this.http2;
}

/**
* Return the absolute temp dir for given web server.
* @param prefix server name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,10 @@ public interface ConfigurableWebServerFactory
*/
void setServerHeader(String serverHeader);

/**
* Sets the Http2 configuration that will be applied to the server's default connector.
* @param http2 the {@link Http2} configuration
*/
void setHttp2(Http2 http2);

}
Loading