brief introduction
In the last article, we mentioned how to configure TLS in netty to support http2. In fact, TLS is not a mandatory requirement of https. It is just a recommended standard. In addition to TLS, how do I set up netty to support http2? Let's have a look.
Basic process
netty supports http2 in two cases. The first case is to use tls. In this case, you need to add a protocol negotiation handler to negotiate the protocol after the handshake. After negotiation, you need to decide which protocol to use.
In the last article, we introduced the details of TLS supporting http2. I won't repeat it here. Interested friends can check my previous articles.
If tls is not used, there are two situations. One is to directly use http1.1. We need to add a ChannelInboundHandler for http1.1.
Another case is to use clear text to upgrade from HTTP 1.1 to HTTP 2.
HTTP/2 ClearText is also called h2c. Let's look at a simple upgrade request. First, the client request:
GET /index HTTP/1.1 Host: server.flydean.com Connection: Upgrade, HTTP2-Settings Upgrade: h2c HTTP2-Settings: (SETTINGS payload) Copy code
Then there is the response from the server. If the server does not support upgrading, it returns:
HTTP/1.1 200 OK Content-length: 100 Content-type: text/html (... HTTP/1.1 response ...) Copy code
If the server supports upgrade, return:
HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: h2c (... HTTP/2 response ...) Copy code
CleartextHttp2ServerUpgradeHandler
With the above basic process, we only need to provide the corresponding handler class in netty to solve the support of netty for http2.
However, the above upgrade process looks complex, so netty provides us with an encapsulated class: cleartexthttp2server upgradehandler to implement the functions of h2c.
This class needs to pass in three parameters: HttpServerCodec, HttpServerUpgradeHandler and ChannelHandler.
HttpServerCodec is a coding class that handles http server. Generally, we use HttpServerCodec.
HttpServerUpgradeHandler is a processing class upgraded from http1.1 to http2.
netty also provides a ready-made class: HttpServerUpgradeHandler to handle the upgraded coding.
HttpServerUpgradeHandler requires two parameters, one is sourceCodec, which is the original HTTP coding class HttpServerCodec, the other is the factory class used to return UpgradeCodec, and the http2server UpgradeCodec provided by netty.
public HttpServerUpgradeHandler(SourceCodec sourceCodec, UpgradeCodecFactory upgradeCodecFactory) { this(sourceCodec, upgradeCodecFactory, 0); } Copy code
ChannelHandler is the handler that really handles HTTP2. We can customize this handler as needed.
With the UpgradeHandler, you can add it to the ChannelPipeline.
Http2ConnectionHandler
Whether HttpServerUpgradeHandler or cleartexthttp2server upgradehandler, you need to pass in a handler that can actually handle http2. This handler is Http2ConnectionHandler.
Http2ConnectionHandler is an implementation class. It has implemented the processing of various inbound frame events, and then delegate these events to Http2FrameListener.
Therefore, Http2ConnectionHandler needs to be used with Http2FrameListener.
Here we will explain in detail the Http2FrameListener, which mainly handles various events of the HTTP2 frame.
Let's take a look at the event trigger method provided in http2FrameListener:
As can be seen from the above figure, there are mainly event triggering methods for various frames, including the following frames in http2:
- DATA frame
- HEADERS frame
- PRIORITY frame
- RST_STREAM frame
- SETTINGS acknowledgment frame
- SETTINGS frame
- PING frame
- PING acknowledgment
- PUSH_PROMISE frame
- GO_AWAY frame
- WINDOW_UPDATE frame
- Unknown Frame
These frames basically list all types in the http2 frame.
All we need to do is customize a handler class, inherit Http2ConnectionHandler, and then implement the Http2FrameListener interface.
public final class CustHttp2Handler extends Http2ConnectionHandler implements Http2FrameListener Copy code
In the process of upgrading from HTTP1.1 to http2 using clear text, we need to handle two things. The first thing is to upgrade HTTP1.1 to http2 using HTTP header. You can override the userEventTriggered method inherited from Http2ConnectionHandler and trigger the method in the corresponding Http2FrameListener interface by judging whether the event type is UpgradeEvent, For example, onHeadersRead here:
/** * Handling HTTP upgrade events */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof HttpServerUpgradeHandler.UpgradeEvent) { HttpServerUpgradeHandler.UpgradeEvent upgradeEvent = (HttpServerUpgradeHandler.UpgradeEvent) evt; onHeadersRead(ctx, 1, upgradeToHttp2Headers(upgradeEvent.upgradeRequest()), 0 , true); } super.userEventTriggered(ctx, evt); } Copy code
The upgradeToHttp2Headers method converts the incoming FullHttpRequest into Http2Headers:
private static Http2Headers upgradeToHttp2Headers(FullHttpRequest request) { CharSequence host = request.headers().get(HttpHeaderNames.HOST); Http2Headers http2Headers = new DefaultHttp2Headers() .method(HttpMethod.GET.asciiName()) .path(request.uri()) .scheme(HttpScheme.HTTP.name()); if (host != null) { http2Headers.authority(host); } return http2Headers; } Copy code
Another method to be implemented is the sendResponse method, which writes data back to the client. The writeback needs to include headers and data, as shown below:
/** * Send response data to client */ private void sendResponse(ChannelHandlerContext ctx, int streamId, ByteBuf payload) { Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText()); encoder().writeHeaders(ctx, streamId, headers, 0, false, ctx.newPromise()); encoder().writeData(ctx, streamId, payload, 0, true, ctx.newPromise()); } Copy code
summary
At this point, a handler that handles the upgrade of clear text from HTTP 1.1 to HTTP 2 is ready. With the support of TLS extension protocol explained earlier, a complete netty server supporting http2 is formed.
Author: what about the program
Link: https://juejin.cn/post/7021773501883711501