pippo-java / pippo

Micro Java Web Framework
http://www.pippo.ro
Apache License 2.0
790 stars 128 forks source link

Servlet 4 and HTTP2 #490

Open decebals opened 5 years ago

decebals commented 5 years ago

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

decebals commented 5 years ago

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

decebals commented 5 years ago

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:

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

The important columns (right table) are:

Code:

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 commented 5 years ago

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 commented 5 years ago

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.

whyicantusemyemailasusername commented 5 years ago

http2 on undertow works out of the box

decebals commented 5 years ago

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.