Jetty 9.3 supports HTTP/2 as defined by RFC7540 and it is extremely simple to enable and get started using this new protocol that is available in most current browsers.

Getting started with Jetty 9.3

Before we can run HTTP/2, we need to setup Jetty for HTTP/1.1 (strictly speaking this is not required, but makes for an easy narrative):

$ cd /tmp
$ wget http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.3.0.RC1/jetty-distribution-9.3.0.RC1.tar.gz
$ tar xfz jetty-distribution-9.3.0.RC1.tar.gz
$ export JETTY_HOME=/tmp/jetty-distribution-9.3.0.RC1
$ mkdir demo
$ cd demo
$ java -jar $JETTY_HOME/start.jar --add-to-startd=http,https,deploy
$ cp $JETTY_HOME/demo-base/webapps/async-rest.war webapps/ROOT.war
$ java -jar $JETTY_HOME/start.jar

The result of these commands is to:

  • Download the RC1 release of Jetty 9.3 and unpack it to the /tmp directory
  • Create a demo directory and set it up as a jetty base.
  • Enable the HTTP and HTTPS connectors
  • Deploy a demo web application
  • Start the server!

Now you are running Jetty and you can see the demo application deployed by pointing your browser at http://localhost:8080 or https://localhost:8443 (you may have to accept the self signed SSL certificate)!

In the console output, I’ll draw your attention to the following two INFO lines that should have been logged:

Started ServerConnector@490ab905{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
Started ServerConnector@69955f9a{SSL,[ssl, http/1.1]}{0.0.0.0:8443}

These lines indicate that the server is listening on ports 8080 and 8443 and lists the default and optional protocols that are support on each of those connections.  So you can see that port 8080 supports HTTP/1.1 (which by specification supports HTTP/1.0) and port 8443 supports SSL plus HTTP/1.1 (which is HTTPS!).

Enabling HTTP/2

Now you can stop the Jetty server by hitting CTRL+C on the terminal, and the following command is all that is needed to enable HTTP/2 on both of these ports and to start the server:

$ java -jar $JETTY_HOME/start.jar --add-to-startd=http2,http2c
$ java -jar $JETTY_HOME/start.jar

This does not create/enable new connectors/ports, but adds the HTTP/2 protocol to the supported protocols of the existing connectors on ports 8080 and 8443.

To access the demo web application with HTTP/2 you will need to point a recent browser to https://localhost:8443/.  You can verify whether your browser supports HTTP/2 here, add extensions to your browser to display an icon in the address bar (see this extension for Firefox). Firefox also sets a fake response header: X-Firefox-Spdy: h2.

How does it work?

If you now look at the console logs you will see that additional protocols have been added to both existing connectors on 8080 and 8443:

Started ServerConnector@4bec1f0c{HTTP/1.1,[http/1.1, h2c, h2c-17, h2c-14]}{0.0.0.0:8080}
Started ServerConnector@5bc63d63{SSL,[ssl, alpn, h2, h2-17, h2-14, http/1.1]}{0.0.0.0:8443}

The name ‘h2’ is the official abbreviation for HTTP/2 over TLS  and ‘h2c’ is the abbreviation for unencrypted HTTP/2 (they really wanted to save every bite in the protocol!).   So you can see that port 8080 is now listening by default for HTTP/1.1, but can also talk h2c (and the draft versions of that).   Port 8443 now by defaults talks SSL, then uses ALPN to negotiate a protocol from: ‘h2’, ‘h2-17’, ‘h2-14’ or ‘http/1.1’ in that priority order.

When you point your browser at https://localhost:8443/ it will establish a TLS connection and then use the ALPN extension to negotiate the next protocol.  If both the client and server speak the same version of HTTP/2, then it will be selected, otherwise the connection falls back to HTTP/1.1.

For port 8080, the use of ‘h2c’ is a little more complex.  Firstly there is the problem of finding a client that speaks plain text HTTP/2, as none of the common browsers will use the protocol on plain text connections.  The cUrl utility does support h2c, as of does the Jetty HTTP/2 client.

The default protocol on port 8080 is still HTTP/1.1, so that the initial connection will be expected to speak that protocol. To use the HTTP/2 protocol a connection may send a HTTP/1.1 request that carries  an Upgrade header, which the server may accept and upgrade to any of the other protocols listed against the connector (eg ‘h2’, ‘h2-17’ etc.) by sending a 101 switching protocols response!   If the server does not wish to accept the upgrade, it can respond to the HTTP/1.1 request and continue normally.

However, clients are also allowed to assume that a known server does speak HTTP/2 and can attempt to make a connection to port 8080 and immediately start talking HTTP/2.   Luckily the protocol has been designed with a preamble that looks a bit like a HTTP/1.1 request:

PRI * HTTP/2.0
SM

Jetty’s HTTP/1.1 implementation is able to detect that preamble and if the connector also supports ‘h2c’, then the connection is upgraded without the need for a 101 Switching Protocols response!

HTTP/2 Configuration

Configuration of HTTP/2 can be considered in the following parts

Properties Configuration File Purpose
start.d $JETTY_HOME/etc
ssl.ini jetty-ssl.xml Connector configuration (eg port) common to HTTPS and HTTP/2
ssl.ini jetty-ssl-context.xml Keystore  configuration common to HTTPS and HTTP/2
https.ini jetty-https.xml HTTPS Protocol configuraton
http2.ini jetty-http2.xml HTTP/2 Protocol configuration