Jetty Ssl Factory Using Http2 Doesn't Work

I have a simple spring boot project using jetty.

I run on port 443 and use http1.1 just fine

@Bean(name = "containerCustomizer")
public WebServerFactoryCustomizer containerCustomizer()
{
    return (container -> ((JettyServletWebServerFactory) container).addServerCustomizers(server -> {
        // HTTPS
        SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
        sslContextFactory.setKeyStoreResource(Resource.newResource(
                getClass().getClassLoader().getResource("keystore.jks")));
        sslContextFactory.setKeyStorePassword("password");
        sslContextFactory.setProtocol("TLS");
        sslContextFactory.setKeyStoreType("JKS");

        HttpConfiguration https = new HttpConfiguration();
        https.addCustomizer(new SecureRequestCustomizer());
        SslConnectionFactory sslFactory = new SslConnectionFactory(sslContextFactory,
                                                                   HttpVersion.HTTP_1_1.asString());
        ServerConnector sslConnector = new ServerConnector(server, sslFactory, new HttpConnectionFactory(https));
        sslConnector.setPort(443);
        server.setConnectors(new Connector[] {sslConnector});
    }));
}

However once I change to HTTP2 by replacing HttpVersion.HTTP_1_1.asString() with HttpVersion.HTTP_2.asString() then I get exception

Caused by: java.lang.IllegalStateException: No protocol factory for SSL next protocol: 'HTTP/2.0' in ServerConnector@61e45f87{SSL, (ssl, http/1.1)}{0.0.0.0:443}
    at org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:317) ~[jetty-server-9.4.35.v20201120.jar:9.4.35.v20201120]
    at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:81) ~[jetty-server-9.4.35.v20201120.jar:9.4.35.v20201120]
    at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:234) ~[jetty-server-9.4.35.v20201120.jar:9.4.35.v20201120]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73) ~[jetty-util-9.4.35.v20201120.jar:9.4.35.v20201120]
    at org.springframework.boot.web.embedded.jetty.JettyWebServer.start(JettyWebServer.java:174) ~[spring-boot-2.3.7.RELEASE.jar:2.3.7.RELEASE]
    ... 16 common frames omitted

1 Answer

Just changing the version string isn't sufficient.

You'll also need ...

  • ALPNServerConnectionFactory - for processing the TLS layer (known as ALPN) that selects the HTTP/2 protocol
  • HTTP2ServerConnectionFactory - for using HTTP/2 protocol

As seen in the embedded / Http2Server.java example

The key is that you will chain the connection types together, ALPN to HTTP2 to HTTPS.

// SSL Context Factory for HTTPS and HTTP/2
SslContextFactory sslContextFactory = new SslContextFactory.Server();
// configure sslContextFactory

// HTTPS Configuration
HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
httpsConfig.addCustomizer(new SecureRequestCustomizer());

// HTTP/2 Connection Factory
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig);

ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
alpn.setDefaultProtocol(http.getDefaultProtocol());

// SSL Connection Factory
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol());

// HTTP/2 Connector
ServerConnector http2Connector =
    new ServerConnector(server, ssl, alpn, h2, new HttpConnectionFactory(httpsConfig));
http2Connector.setPort(securePort);
server.addConnector(http2Connector);
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Alexander Ross

Alexander Ross

Gaming, Esports & Interactive Media Writer

Alexander Ross has covered the video game industry for a decade, writing deep dives on game design, esports tournaments, VR developments, and gaming culture.

Share this article
Twitter Facebook Pinterest