HTTP/2 avec Tomcat

Le support de HTTP/2 a été ajouté dans Tomcat 9, et backporté dans Tomcat 8.5.


Ça a été implémenté avec quelques contraintes :


SSL/TLS

Tout d'abord, il faut configurer un connecteur avec SSL/TLS.

Il est très fortement conseillé d'utiliser la version la plus récente de TLS, car les navigateurs peuvent refuser la connexion HTTP/2 si TLS est ancien. En 2017, Firefox 55 et Chrome 61 n'acceptent de se connecter qu'en TLS 1.2.

Upgrade et ALPN

On modifie notre connecteur TLS pour y configurer l'upgrade vers HTTP/2.

   <Connector port="8543" SSLEnabled="true">
       <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
       ...
   </Connector>

Si notre client (navigateur) et notre plateforme supportent ALPN, alors les communications se feront en HTTP/2.

ALPN et Java

Le support d'ALPN a été ajouté dans Java 9. Tomcat se basant dessus pour ses connecteurs JSSE (pur Java), ces derniers ne pourront pas faire de HTTP/2 en Java 8.

La configuration suivante ne fonctionne donc qu'à partir de Java 9 :

   <Connector port="8443" SSLEnabled="true" 
              protocol="org.apache.coyote.http11.Http11NioProtocol"
              sslImplementationName="org.apache.tomcat.util.net.jsse.JSSEImplementation">
       <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
       <SSLHostConfig>
           <Certificate certificateKeystoreFile="conf/tomcat.pfx" certificateKeystorePassword="tomcat"/>
       </SSLHostConfig>
   </Connector>

D'ailleurs, en démarrant en Java 8, on peut lire ça dans les logs :

31-Sep-2017 16:64:00.666 SEVERE [main] org.apache.coyote.http11.AbstractHttp11Protocol.configureUpgradeProtocol 
The upgrade handler [org.apache.coyote.http2.Http2Protocol] for [h2] only supports upgrade via ALPN but has 
been configured for the ["https-jsse-nio-8443"] connector that does not support ALPN.

Alors qu'en Java 9 :

31-Sep-2017 16:64:00.666 INFO [main] org.apache.coyote.http11.AbstractHttp11Protocol.configureUpgradeProtocol 
The ["https-jsse-nio-8443"] connector has been configured to support negotiation to [h2] via ALPN

ALPN et OpenSSL

En Java 8, on ne peut utiliser qu'un connecteur avec un SSL géré en mode OpenSSL. Ça signifie qu'il faut installer Tomcat Native avec un connecteur APR ou NIO+OpenSSL.

   <Connector port="8443" SSLEnabled="true" 
              protocol="org.apache.coyote.http11.Http11NioProtocol"
              sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation">
       <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
       <SSLHostConfig>
           <Certificate certificateKeystoreFile="conf/tomcat.pfx" certificateKeystorePassword="tomcat"/>
       </SSLHostConfig>
   </Connector>

Et si c'est bien configuré, on devrait voir le même log :

31-Sep-2017 16:64:00.666 INFO [main] org.apache.coyote.http11.AbstractHttp11Protocol.configureUpgradeProtocol 
The ["https-openssl-apr-8443"] connector has been configured to support negotiation to [h2] via ALPN

Références

https://tomcat.apache.org/tomcat-9.0-doc/config/http.html#HTTP/2_Support https://gist.github.com/hasalex/7db64e64c77d1ce996c4b9ba89732f7f