I have upgraded a Jetty 9.2 HTTP/1.1 + SSL only server (embedded) to Jetty 9.3.0 (v20150612) HTTP/HTTPS 2.0 (SLL(TLS)-ALPN-HTTP/2). I use JRE 8 (Oracle 1.8.0 Build 45 - b15) and Eclipse.
* PROBLEM SOLVED BY ANSWER OF JOAKIM : see end of post for solution *
Before the upgrade HTTP and HTTPS worked fine and it still did by simply rebuilding with the Jetty 9.3 Jar files. Then I upgraded the code (learning from the examples that I managed to find) to incorporate SSL(TLS)-ALPN-HTTP/2-HTTP/1.1. The main example I used is in this link with code
A Google Chrome (Version 43.0.2357.130 m) Browser works fine with an http request such as http:// 10.32.1.110:8080/ and the web page displays. But if I open a second tab and try https:// 10.32.1.110:8443/ I receive an error ERR_EMPTY_RESPONSE. I can however connect to webtide.com and get an https session. The interference of a firewall on my system has been excluded. 10.32.??? connections are not passing it as well for the working HTTP as for the failing HTTPS.
This error does NOT block the Jetty server (the server doesn't throw or log an error) and I can go back to the first browser tab and continue to request the web page and I see it updated (I have a time-stamp and counter in it) each time.
In the HTTPS case my handle() method isn't called by Jetty (I have a log line to monitoring that) and I see only the HTTP requests come in the handle() method. The http requests that do arrive in my handle() are of type HTTP/1.1 according to the Jetty request object. According my research that is normal because Google Chrome will NOT do HTTP/2 without SSL/ALPN.
I have been thinking in the direction of SSL and ALPN problems as the reason that HTTPS requests result in the ERR_EMPTY_RESPONSE. The alpn-api-1.1.2.v20150522.jar is added to my Eclipse VM Arguments (JVM Boot classpath equivalent) as "-Xbootclasspath/p:D:\Users\TWO\DATA\Eclipse\alpn-api-1.1.2.v20150522\alpn-api-1.1.2.v20150522.jar" Since then Jetty doesn't complain about ALPN not being on the JVM boot classpath (by throwing an error as it did before). From the Jetty log below the SLL and HTTP/2 are started correctly too.
The Jetty Server starts normally with these logs:
2015-06-24 15:53:29.292:INFO:oejs.Server:main: jetty-9.3.0.v20150612
2015-06-24 15:53:29.323:INFO:oejs.ServerConnector:main: Started ServerConnector@123772c4{HTTP/1.1,[http/1.1, h2c, h2c-17, h2c-16, h2c-15, h2c-14]}{0.0.0.0:8080}
2015-06-24 15:53:29.338:INFO:oejus.SslContextFactory:main: x509={jetty.eclipse.org=jetty} wild={} alias=null for SslContextFactory@6f75e721(file:///D:/Users/[removed]/keystores/keystore,file:///D:/Users/[removed]/keystores/keystore)
2015-06-24 15:53:29.495:INFO:oejs.ServerConnector:main: Started ServerConnector@13deb50e{SSL,[ssl, alpn, h2, h2-17, h2-16, h2-15, h2-14, http/1.1]}{0.0.0.0:8443}
2015-06-24 15:53:29.495:INFO:oejs.Server:main: Started @321ms
Here is the relevant Java server code:
... standard Jetty imports plus
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
import org.eclipse.jetty.http2.HTTP2Cipher;
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
QueuedThreadPool oTP = new QueuedThreadPool(20);
this.oServer = new Server(oTP);
this.oServer.setHandler((Handler) this);
HttpConfiguration httpcfg = new HttpConfiguration();
httpcfg.setSecureScheme("https");
httpcfg.setSecurePort(8443);
HttpConnectionFactory httpF=new HttpConnectionFactory(httpcfg);
HTTP2CServerConnectionFactory http2F=new HTTP2CServerConnectionFactory(httpcfg);
ServerConnector http=new ServerConnector(this.oServer,httpF,http2F);
http.setPort(8080);
this.oServer.addConnector(http);
SslContextFactory sslCF=new SslContextFactory();
sslCF.setKeyStorePath(MetaWebServerConfig.getWebServerKeystore()+"keystore");
sslCF.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslCF.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
sslCF.setTrustStorePath(MetaWebServerConfig.getWebServerKeystore()+"keystore");
sslCF.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslCF.setExcludeCipherSuites(
"SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
sslCF.setCipherComparator(new HTTP2Cipher.CipherComparator());
HttpConfiguration httpscfg = new HttpConfiguration(httpcfg);
httpscfg.addCustomizer(new SecureRequestCustomizer());
HTTP2ServerConnectionFactory h2F=new HTTP2ServerConnectionFactory(httpscfg);
NegotiatingServerConnectionFactory.checkProtocolNegotiationAvailable();
ALPNServerConnectionFactory alpnF=new ALPNServerConnectionFactory();
alpnF.setDefaultProtocol(http.getDefaultProtocol());
SslConnectionFactory sslF=new SslConnectionFactory(sslCF,alpnF.getProtocol());
HttpConnectionFactory https2F=new HttpConnectionFactory(httpscfg);
ServerConnector http2=new ServerConnector(this.oServer,sslF,alpnF,h2F,https2F);
http2.setPort(8443);
this.oServer.addConnector(http2);
ALPN.debug=false;
this.oServer.start();
On request of gregw I tried the sample code that is in the link on the top. I only modified the path to the keystorefor the SslContextFactory. I always use the same keystore file because I know it is ok (see beginning of post - my old HTTP/1.1+SLL worked and used that same keystore.
2015-06-25 14:07:14.972:INFO:oejs.Server:main: jetty-9.3.0.v20150612
2015-06-25 14:07:15.019:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@6f75e721{/,file:///D:/Users/[path]/docroot,AVAILABLE}
2015-06-25 14:07:15.082:INFO:oejs.ServerConnector:main: Started ServerConnector@1888ff2c{HTTP/1.1,[http/1.1, h2c, h2c-17, h2c-16, h2c-15, h2c-14]}{0.0.0.0:8080}
2015-06-25 14:07:15.097:INFO:oejus.SslContextFactory:main: x509={jetty.eclipse.org=jetty} wild={} alias=null for SslContextFactory@4b952a2d(file:///D:/Users/[path]/keystores/keystore,null)
2015-06-25 14:07:15.269:INFO:oejs.ServerConnector:main: Started ServerConnector@5594a1b5{SSL,[ssl, alpn, h2, h2-17, h2-16, h2-15, h2-14, http/1.1]}{0.0.0.0:8443}
2015-06-25 14:07:15.269:INFO:oejs.Server:main: Started @587ms
Accessing with http works but with https not and browser shows ERR_EMPTY_RESPONSE again.
Tried using IExplorer 11. Same results. Works for http not for https (msg = This page can’t be displayed) not to confuse with 404 (This page cannot be found). IE, in contrast to Chrome did give the 'Cookie' warning when greg's code was used with http but it did not with https.
Is there someone that may have an idea how to solve the above problem. TIA
* SOLUTION *
As suggested by Joakim I added the alpn-boot-8.1.3.v20150130.jar in stead of the alpn-api-1.1.2.v20150522.jar to the boot classpath. Tests reulted in the following combinations working perfectly:
- HTTP/1.1 (HTTP) - done with Google Chrome
HTTP/1.1 (HTTP) - second try done with IE
HTTP/2.0 + SSL (HTTPS) - done with Google Chrome
HTTP/1_1 + SLL (HTTPS) - done with IE
HTTP/2_0 (HTTP) - didn't test by lack of quick User Agent doing it.
These are the only future combinations I am interested in although I am sure that HTTP/2_0 with SSL will also work.
This Jetty Documentation link shows the table between JRE version and ALPN JAR file versions to use in case one has the same problem with another JRE.
Many thanks to all that tried to help solve this.
For Oracle/OpenJDK Java JRE/JDK you use alpn-boot.jar, not alpn-api.jar ...
See ALPN / Versions documentation for table of Java to alpn-boot versions.
This is vitally important, as this modifies the SSL/TLS layer of Java itself to add support for the ALPN protocol, required by HTTP/2 to function.
This -Xbootclasspath requirement is mandatory until such time in the future when Java ships with ALPN built-in (which is scheduled for Java 9)