Die Version 2 des HTTP-Protokolls ist eigentlich dafür gedacht, nur mit SSL- bzw. TLS-Verschlüsselung verwendet zu werden. Dennoch ist es möglich, und für Testzwecke unter Umständen auch sinnvoll, die Variante h2c (HTTP/2 Cleartext) zu verwenden. Dabei findet keine Verschlüsselung statt. Kein Webbrowser und nur wenige Webserver unterstützen so etwas.
Der Java-basierte Webserver Jetty jedoch schon. Damit ist es möglich, eine kleine, auf Spring Boot basierende Beispiel-Anwendung zu bauen, um ein wenig mit h2c und HTTP-Protokoll-Upgrades herumzuspielen.
Alles, was man dazu braucht, ist eine Spring-Boot-Anwendung, bei der man den enthaltenen Spring-Boot-Webserver mit einer h2c-ConnectionFactory ausstattet:
@SpringBootApplication public class App { @Bean public EmbeddedServletContainerCustomizer customizer() { return container -> { if (container instanceof JettyEmbeddedServletContainerFactory) { ((JettyEmbeddedServletContainerFactory) container) .addServerCustomizers(server -> { ServerConnector sc = (ServerConnector) server .getConnectors()[0]; sc.addConnectionFactory( new HTTP2CServerConnectionFactory(new HttpConfiguration()) ); } ); } }; } public static void main(String[] args) { SpringApplication.run(App.class, args); } }
Wenn diese Spring-Anwendung nun einen einfachen Webservice implementiert, der über den HTTP-Port 8080 angeboten wird, spricht dieser zunächst einmal ganz einfaches HTTP/1.1.
Der HTTP-Client hat jedoch die Möglichkeit, mithilfe eines Protokoll-Upgrades einen Umstieg von HTTP/1.1 auf h2c zu fordern.
Dies kann mit einem einfachen Test-Werkzeug, wie beispielsweise nghttp ausprobiert werden:
$ nghttp -vua http://localhost:8080/hello-world
Nghttp führt einen GET-Request auf die Ressource /hello-world
aus. Die Parameter -vua
bewirken neben einer ausführlichen Text-Ausgabe des Befehls auch ein Protokoll-Upgrade.
[ 0.002] Connected [ 0.002] HTTP Upgrade request GET /hello-world?name=Jan HTTP/1.1 host: localhost:8080 connection: Upgrade, HTTP2-Settings upgrade: h2c http2-settings: AAMAAABkAAQAAP__ accept: */* user-agent: nghttp2/1.17.0 [ 0.003] HTTP Upgrade response HTTP/1.1 101 Switching Protocols [ 0.003] HTTP Upgrade success [ 0.005] recv HEADERS frame <length=67, flags=0x04, stream_id=1>; END_HEADERS (padlen=0); First response header {"id":19,"content":"Hello, World!"} [ 0.005] recv DATA frame <length=33, flags=0x00, stream_id=1>
Wir sehen also, dass die Spring-Anwendung sowohl HTTP/1.1/ als auch h2c über denselben Port 8080 anbieten kann.
Auf eine ähnliche Art und Weise lassen sich Spring-Boot-Services auch um HTTP/2-Konnektoren erweitern. Sie können also mit wenigen zusätzlichen Code-Zeilen dazu gebracht werden, HTTP/2 anzubieten.
Dies funktioniert dann natürlich nur mit SSL/TLS-Verschlüsselung.
Wie das funktioniert, wird auf diesem Blog in Kürze in einem weiteren Artikel erklärt.
Das komplette Code-Beispiel zu diesem Artikel ist bei Github verfügbar.
Bild: Creative Commons Attribution-Share Alike 4.0 International license. Autor: Diseño Web Valencia