pippo icon indicating copy to clipboard operation
pippo copied to clipboard

Servlet 4 and HTTP2

Open decebals opened this issue 6 years ago • 6 comments

The idea is to play with Servlet 4 and see how we can add support for HTTP2 in Pippo.

decebals avatar Jan 17 '19 08:01 decebals

It's related with #487. Actually, #487 is a subtask/subset of this issue.

decebals avatar Jan 17 '19 08:01 decebals

Good news. I have a POC (a demo) for HTTP/2 in Pippo. Before to present you the code I will give you some information:

  • the demo use Jetty server (but this aspect is not so important because when the feature will be available, Tomcat and Undertow will support also this feature)
  • the demo present you how to use HTTP/2 server PUSH
  • the demo is tiny (only a route that serve a dynamic html page using template page)
  • HTTP/2 protocol will be enabled by default if you supply a keystore file (SSL)

So, now I can show the code and some pictures:

  • HTTP 1.1 screenshot from 2019-01-23 22-44-02
  • HTTP/2 (H2) screenshot from 2019-01-23 22-41-04
  • HTTP/2 with PUSH screenshot from 2019-01-23 22-39-48

The important columns (right table) are:

  • Protocol
  • Initiator

Code:

  • application.properties
# SSL configuration
server.keystoreFile = keystore.jks
server.keystorePassword = password
server.truststoreFile = truststore.jks
server.truststorePassword = password

I posted the code on gist to have a lite comment here. In that code you can see that I implemented one of my idea, to extract automatically the assets/resources needed by the html page that will be send as response to the client. For extraction I used a HTML parser. Sure we can avoid this new dependency, because we don't need a full html parser. We can write a small class that can extract only the information needed for push. My final idea is to abstract all push mechanism in Response class. A simple push enabled flag/method in Response class from Pippo will be enough to push out of the box (automatically) all the assets of the page.

On my test branch I switched Pippo from Servlet 3.x to Servlet 4 to use the new features. The process was painless. Unfortunately the last Jetty version (9.4) doesn't implement Servlet 4 specification and from this reason I used in my demo the Jetty specific API. For the servers that implement already Servlet 4 specs, we will use javax.servlet.http.PushBuilder returned by HttpServletRequest#newPushBuilder method.

In the end, I can say that the code looks simple enough and it was a pleasure to work on/with this feature.

Any feedback is welcome.

decebals avatar Jan 23 '19 22:01 decebals

To switch my HTTP/2 demo from Jetty to Undertow, all I made is to upgrade Undertow to the last version (2.0.17.Final). I remember you that I updated Servlet version to 4.0 in pippo-core, so we can use the javax.servlet.http.PushBuilder:

HttpServletRequest httpServletRequest = routeContext.getRequest().getHttpServletRequest();
PushBuilder pushBuilder = httpServletRequest.newPushBuilder();
getPushResourcePaths(html).forEach(path -> pushBuilder.path(path).push());

decebals avatar Jan 24 '19 14:01 decebals

On Tomcat I encounter some problem. After I made some modifications in TomcatServer to enable HTTP/2:

private void enableSSLConnector(Tomcat tomcat) {
    // actual code

    // enable HTTP/2
    connector.setAttribute("sslImplementationName", "org.apache.tomcat.util.net.openssl.OpenSSLImplementation");
//    connector.setAttribute("sslImplementationName", "org.apache.tomcat.util.net.jse.JSSEImplementation");
    connector.addUpgradeProtocol(new Http2Protocol());
}

To go with OpenSSLImplementation you must install APR and Tomcat Native on your computer. On my dev machine I use Ubuntu 18.10 I installed all these dependencies via apt-get.

decebal@decebal:/usr/lib$ ldd libtcnative-1.so.0.2.17 
	linux-vdso.so.1 (0x00007ffd61da7000)
	libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f2f2c9d9000)
	libcrypto.so.1.1 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007f2f2c70e000)
	libapr-1.so.0 => /usr/lib/x86_64-linux-gnu/libapr-1.so.0 (0x00007f2f2c6d6000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f2f2c6b5000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2f2c4cb000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2f2c4c5000)
	libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007f2f2c4ba000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f2f2ccb9000)

When I run demo I obtain the below error message:

22:11:43 [main] INFO ro.pippo.tomcat.TomcatServer - Starting Tomcat Server 9.0.10 on port 8338
Jan 26, 2019 10:11:44 PM org.apache.coyote.http11.AbstractHttp11Protocol configureUpgradeProtocol
INFO: The ["https-openssl-nio-8338"] connector has been configured to support negotiation to [h2] via ALPN
Jan 26, 2019 10:11:44 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["https-openssl-nio-8338"]
Jan 26, 2019 10:11:44 PM org.apache.catalina.util.LifecycleBase handleSubClassException
SEVERE: Failed to initialize component [Connector[HTTP/1.1-8338]]
java.lang.UnsatisfiedLinkError: org.apache.tomcat.jni.Pool.create(J)J
	at org.apache.tomcat.jni.Pool.create(Native Method)
	at org.apache.tomcat.util.net.openssl.OpenSSLEngine.<clinit>(OpenSSLEngine.java:70)
	at org.apache.tomcat.util.net.openssl.OpenSSLUtil.getImplementedProtocols(OpenSSLUtil.java:61)
	at org.apache.tomcat.util.net.SSLUtilBase.<init>(SSLUtilBase.java:53)
	at org.apache.tomcat.util.net.openssl.OpenSSLUtil.<init>(OpenSSLUtil.java:41)
	at org.apache.tomcat.util.net.openssl.OpenSSLImplementation.getSSLUtil(OpenSSLImplementation.java:36)

Maybe someone who uses Tomcat and who has more experience like me with Tomcat can help.

decebals avatar Jan 26 '19 20:01 decebals

http2 on undertow works out of the box

http2 on undertow works out of the box

Yes. I said the same thing in https://github.com/pippo-java/pippo/issues/490#issuecomment-457213332.

decebals avatar Mar 11 '19 17:03 decebals