Skip to content

Commit 6d3e6cb

Browse files
committed
Jetty http/2 support jooby-project#418
1 parent 8779643 commit 6d3e6cb

9 files changed

Lines changed: 142 additions & 42 deletions

File tree

jooby-jetty/pom.xml

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@
4545
</dependency>
4646

4747
<dependency>
48-
<groupId>org.eclipse.jetty</groupId>
49-
<artifactId>jetty-continuation</artifactId>
48+
<groupId>org.eclipse.jetty.http2</groupId>
49+
<artifactId>http2-server</artifactId>
5050
<version>${jetty.version}</version>
5151
</dependency>
5252

@@ -55,6 +55,12 @@
5555
<artifactId>websocket-server</artifactId>
5656
</dependency>
5757

58+
<dependency>
59+
<groupId>org.eclipse.jetty</groupId>
60+
<artifactId>jetty-alpn-server</artifactId>
61+
<version>${jetty.version}</version>
62+
</dependency>
63+
5864
<!-- Test dependencies -->
5965
<dependency>
6066
<groupId>org.jooby</groupId>
@@ -110,4 +116,55 @@
110116

111117
</dependencies>
112118

119+
<profiles>
120+
<profile>
121+
<id>linux</id>
122+
<activation>
123+
<os>
124+
<family>linux</family>
125+
</os>
126+
</activation>
127+
<dependencies>
128+
<dependency>
129+
<groupId>io.netty</groupId>
130+
<artifactId>netty-tcnative-boringssl-static</artifactId>
131+
<version>1.1.33.Fork19</version>
132+
<classifier>linux-x86_64</classifier>
133+
</dependency>
134+
</dependencies>
135+
</profile>
136+
<profile>
137+
<id>windows_x86</id>
138+
<activation>
139+
<os>
140+
<family>windows</family>
141+
</os>
142+
</activation>
143+
<dependencies>
144+
<dependency>
145+
<groupId>io.netty</groupId>
146+
<artifactId>netty-tcnative-boringssl-static</artifactId>
147+
<version>1.1.33.Fork19</version>
148+
<classifier>windows-x86_64</classifier>
149+
</dependency>
150+
</dependencies>
151+
</profile>
152+
<profile>
153+
<id>mac_x86_64</id>
154+
<activation>
155+
<os>
156+
<family>mac</family>
157+
</os>
158+
</activation>
159+
<dependencies>
160+
<dependency>
161+
<groupId>io.netty</groupId>
162+
<artifactId>netty-tcnative-boringssl-static</artifactId>
163+
<version>1.1.33.Fork19</version>
164+
<classifier>osx-x86_64</classifier>
165+
</dependency>
166+
</dependencies>
167+
</profile>
168+
</profiles>
169+
113170
</project>

jooby-jetty/src/main/java/org/jooby/internal/jetty/JettyServer.java

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import javax.inject.Provider;
3131
import javax.net.ssl.SSLContext;
3232

33+
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
34+
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
3335
import org.eclipse.jetty.server.HttpConfiguration;
3436
import org.eclipse.jetty.server.HttpConnectionFactory;
3537
import org.eclipse.jetty.server.SecureRequestCustomizer;
@@ -54,61 +56,67 @@
5456

5557
public class JettyServer implements org.jooby.spi.Server {
5658

59+
private static final String H2 = "h2";
60+
private static final String H2_17 = "h2-17";
61+
private static final String HTTP_1_1 = "http/1.1";
62+
5763
private static final String JETTY_HTTP = "jetty.http";
5864
private static final String CONNECTOR = "connector";
65+
5966
/** The logging system. */
6067
private final Logger log = LoggerFactory.getLogger(org.jooby.spi.Server.class);
6168

6269
private Server server;
6370

6471
@Inject
65-
public JettyServer(final HttpHandler handler, final Config config,
72+
public JettyServer(final HttpHandler handler, final Config conf,
6673
final Provider<SSLContext> sslCtx) {
67-
this.server = server(handler, config, sslCtx);
74+
this.server = server(handler, conf, sslCtx);
6875
}
6976

70-
private Server server(final HttpHandler handler, final Config config,
71-
final Provider<SSLContext> sslCtx) {
77+
private Server server(final HttpHandler handler, final Config conf,
78+
final Provider<SSLContext> sslCtx) {
7279
System.setProperty("org.eclipse.jetty.util.UrlEncoded.charset",
73-
config.getString("jetty.url.charset"));
80+
conf.getString("jetty.url.charset"));
7481

7582
System.setProperty("org.eclipse.jetty.server.Request.maxFormContentSize",
76-
config.getBytes("server.http.MaxRequestSize").toString());
83+
conf.getBytes("server.http.MaxRequestSize").toString());
7784

78-
QueuedThreadPool pool = conf(new QueuedThreadPool(), config.getConfig("jetty.threads"),
85+
QueuedThreadPool pool = conf(new QueuedThreadPool(), conf.getConfig("jetty.threads"),
7986
"jetty.threads");
8087

8188
Server server = new Server(pool);
8289
server.setStopAtShutdown(false);
8390

8491
// HTTP connector
85-
ServerConnector http = http(server, config.getConfig(JETTY_HTTP), JETTY_HTTP);
86-
http.setPort(config.getInt("application.port"));
87-
http.setHost(config.getString("application.host"));
92+
ServerConnector http = http(server, conf.getConfig(JETTY_HTTP), JETTY_HTTP);
93+
http.setPort(conf.getInt("application.port"));
94+
http.setHost(conf.getString("application.host"));
8895

89-
if (config.hasPath("application.securePort")) {
96+
boolean http2 = conf.getBoolean("server.http2.enabled");
9097

91-
ServerConnector https = https(server, config.getConfig(JETTY_HTTP), JETTY_HTTP,
92-
sslCtx.get());
93-
https.setPort(config.getInt("application.securePort"));
98+
if (conf.hasPath("application.securePort")) {
99+
100+
ServerConnector https = https(server, conf.getConfig(JETTY_HTTP), JETTY_HTTP,
101+
sslCtx.get(), http2);
102+
https.setPort(conf.getInt("application.securePort"));
94103

95104
server.addConnector(https);
96105
}
97106

98107
server.addConnector(http);
99108

100109
WebSocketPolicy wsConfig = conf(new WebSocketPolicy(WebSocketBehavior.SERVER),
101-
config.getConfig("jetty.ws"), "jetty.ws");
110+
conf.getConfig("jetty.ws"), "jetty.ws");
102111
WebSocketServerFactory webSocketServerFactory = new WebSocketServerFactory(wsConfig);
103112
webSocketServerFactory.setCreator((req, rsp) -> {
104113
JettyWebSocket ws = new JettyWebSocket();
105114
req.getHttpServletRequest().setAttribute(JettyWebSocket.class.getName(), ws);
106115
return ws;
107116
});
108117

109-
server.setHandler(new JettyHandler(handler, webSocketServerFactory, config
110-
.getString("application.tmpdir"),
111-
config.getBytes("jetty.http.FileSizeThreshold").intValue()));
118+
server.setHandler(new JettyHandler(handler, webSocketServerFactory, conf
119+
.getString("application.tmpdir"), conf.getBytes("jetty.FileSizeThreshold").intValue()));
112120

113121
return server;
114122
}
@@ -121,11 +129,12 @@ private ServerConnector http(final Server server, final Config conf, final Strin
121129

122130
ServerConnector connector = new ServerConnector(server, httpFactory);
123131

124-
return conf(connector, conf.getConfig(CONNECTOR), path + ".connector");
132+
return conf(connector, conf.getConfig(CONNECTOR), path + "." + CONNECTOR);
125133
}
126134

127135
private ServerConnector https(final Server server, final Config conf, final String path,
128-
final SSLContext sslContext) {
136+
final SSLContext sslContext, final boolean http2) {
137+
129138
HttpConfiguration httpConf = conf(new HttpConfiguration(), conf.withoutPath(CONNECTOR),
130139
path);
131140

@@ -135,12 +144,24 @@ private ServerConnector https(final Server server, final Config conf, final Stri
135144
HttpConfiguration httpsConf = new HttpConfiguration(httpConf);
136145
httpsConf.addCustomizer(new SecureRequestCustomizer());
137146

138-
HttpConnectionFactory httpsFactory = new HttpConnectionFactory(httpsConf);
147+
if (http2) {
148+
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory(H2, H2_17);
149+
alpn.setDefaultProtocol(HTTP_1_1);
139150

140-
ServerConnector connector = new ServerConnector(server,
141-
new SslConnectionFactory(sslContextFactory, "HTTP/1.1"), httpsFactory);
151+
HTTP2ServerConnectionFactory http2Factory = new HTTP2ServerConnectionFactory(httpsConf);
142152

143-
return conf(connector, conf.getConfig(CONNECTOR), path + ".connector");
153+
ServerConnector connector = new ServerConnector(server,
154+
new SslConnectionFactory(sslContextFactory, "alpn"), alpn, http2Factory);
155+
156+
return conf(connector, conf.getConfig(CONNECTOR), path + ".connector");
157+
} else {
158+
HttpConnectionFactory httpsFactory = new HttpConnectionFactory(httpsConf);
159+
160+
ServerConnector connector = new ServerConnector(server,
161+
new SslConnectionFactory(sslContextFactory, HTTP_1_1), httpsFactory);
162+
163+
return conf(connector, conf.getConfig(CONNECTOR), path + ".connector");
164+
}
144165
}
145166

146167
@Override

jooby-jetty/src/main/resources/org/jooby/spi/server.conf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ jetty {
1313
Name = jetty task
1414
}
1515

16+
FileSizeThreshold = 16k
17+
1618
http {
1719
HeaderCacheSize = ${server.http.HeaderSize}
1820

@@ -22,8 +24,6 @@ jetty {
2224

2325
OutputBufferSize = ${server.http.ResponseBufferSize}
2426

25-
FileSizeThreshold = 16k
26-
2727
SendServerVersion = false
2828

2929
SendXPoweredBy = false
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package jetty;
2+
3+
import org.jooby.Jooby;
4+
5+
public class H2 extends Jooby {
6+
7+
{
8+
http2();
9+
securePort(8443);
10+
11+
assets("/assets/**");
12+
assets("/", "index.html");
13+
}
14+
15+
public static void main(final String[] args) throws Throwable {
16+
run(H2::new, args);
17+
}
18+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(function () {
2+
3+
console.log('loaded');
4+
5+
})();
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<script type="text/javascript" src="/assets/index.js"></script>
4+
<body>
5+
<h1>H2</h1>
6+
</body>
7+
</html>

jooby-jetty/src/test/resources/logback.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
</encoder>
77
</appender>
88

9-
<logger name="org.jooby.spi.Server" level="DEBUG" />
10-
119
<root level="INFO">
1210
<appender-ref ref="STDOUT" />
1311
</root>

jooby-netty/pom.xml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,6 @@
5050
<version>${netty.version}</version>
5151
</dependency>
5252

53-
<dependency>
54-
<groupId>org.eclipse.jetty.npn</groupId>
55-
<artifactId>npn-api</artifactId>
56-
<version>8.1.2.v20120308</version>
57-
</dependency>
58-
59-
<dependency>
60-
<groupId>org.mortbay.jetty.alpn</groupId>
61-
<artifactId>alpn-boot</artifactId>
62-
<version>8.1.9.v20160720</version>
63-
</dependency>
64-
6553
<dependency>
6654
<groupId>io.netty</groupId>
6755
<artifactId>netty-handler</artifactId>

jooby/src/main/java/org/jooby/internal/AppPrinter.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public class AppPrinter {
3939

4040
private String[] urls;
4141

42+
private boolean http2;
43+
4244
public AppPrinter(final Set<Route.Definition> routes,
4345
final Set<WebSocket.Definition> sockets,
4446
final Config conf) {
@@ -52,6 +54,7 @@ public AppPrinter(final Set<Route.Definition> routes,
5254
if (conf.hasPath("application.securePort")) {
5355
this.urls[1] = "https://" + host + ":" + conf.getString("application.securePort") + path;
5456
}
57+
http2 = conf.getBoolean("server.http2.enabled");
5558
}
5659

5760
@Override
@@ -66,6 +69,9 @@ public String toString() {
6669
buffer.append("\n ").append(url);
6770
}
6871
}
72+
if (http2) {
73+
buffer.append(" +h2");
74+
}
6975
return buffer.toString();
7076
}
7177

0 commit comments

Comments
 (0)