Introduction
In the previous article, we mentioned how to configure TLS in netty so that it supports HTTP2. In fact, TLS is not a mandatory requirement for https, it is just a recommended standard. So in addition to TLS, how do I need to set up to make netty support http2? Let's take a look.
Basic process
Netty supports http2 in two cases. The first case is to use tls. In this case, a ProtocolNegotiationHandler needs to be added to negotiate the protocol after the handshake. After the negotiation, you need to decide which protocol to use.
In the previous article, we have already introduced the details of TLS support for http2, so I won’t go into details here, and interested friends can check my previous article.
If you do not use tls, then there are two situations, one is to use http1.1 directly, we need to add a ChannelInboundHandler for http1.1.
Another situation is to use clear text to upgrade from HTTP1.1 to HTTP2.
HTTP/2 ClearText is also called h2c. Let’s look at a simple upgrade request. The first is a client request:
GET /index HTTP/1.1
Host: server.flydean.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: (SETTINGS payload)
Then there is the response from the server. If the server does not support the upgrade, it will return:
HTTP/1.1 200 OK
Content-length: 100
Content-type: text/html
(... HTTP/1.1 response ...)
If the server supports upgrade, it returns:
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c
(... HTTP/2 response ...)
CleartextHttp2ServerUpgradeHandler
With the above basic process, we only need to provide the corresponding handler class in netty to solve the netty support for http2.
However, the above upgrade process looks more complicated, so netty provides us with a packaged class: CleartextHttp2ServerUpgradeHandler to realize the function of h2c.
This class needs to pass in 3 parameters, namely HttpServerCodec, HttpServerUpgradeHandler and ChannelHandler.
HttpServerCodec is a coding class that handles http server, generally we use HttpServerCodec.
HttpServerUpgradeHandler is a processing class for upgrading from http1.1 to http2.
netty also provides a ready-made class: HttpServerUpgradeHandler to handle the upgrade encoding.
HttpServerUpgradeHandler requires two parameters, one is sourceCodec, which is the original HTTP encoding class HttpServerCodec, and the other is a factory class used to return UpgradeCodec, which returns the Http2ServerUpgradeCodec that comes with netty.
public HttpServerUpgradeHandler(SourceCodec sourceCodec, UpgradeCodecFactory upgradeCodecFactory) {
this(sourceCodec, upgradeCodecFactory, 0);
}
ChannelHandler is the handler that really handles HTTP2, and we can customize this handler as needed.
With UpgradeHandler, just add it to ChannelPipeline.
Http2ConnectionHandler
Whether it is HttpServerUpgradeHandler or CleartextHttp2ServerUpgradeHandler, you need to pass in a handler that can actually handle http2. This handler is Http2ConnectionHandler.
Http2ConnectionHandler is an implementation class, which has implemented events for processing various inbound frame events, and then delegates these events to Http2FrameListener.
So Http2ConnectionHandler needs to be used in conjunction with Http2FrameListener.
Here is a detailed explanation of Http2FrameListener, which mainly handles various events of HTTP2 frame.
First look at the event trigger method provided in http2FrameListener:
As you can see from the above figure, it is mainly the event triggering methods of various frames, among which there are several types of 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 types of frames basically enumerate all types of http2 frames.
What we have to do is to customize a handler class, inherit Http2ConnectionHandler, and then implement the Http2FrameListener interface.
public final class CustHttp2Handler extends Http2ConnectionHandler implements Http2FrameListener
In the process of upgrading from HTTP1.1 to HTTP2 using clear text, we need to deal with two things. The first thing is to deal with http1.1 to upgrade to http2 using http headers. You can override the userEventTriggered method inherited from Http2ConnectionHandler, and pass judgment Whether the type of event is UpgradeEvent, to trigger the corresponding method in the Http2FrameListener interface, such as onHeadersRead here:
/**
* 处理HTTP upgrade事件
*/
@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);
}
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;
}
There is another method to be implemented, which is the sendResponse method, which writes the data back to the client. The write-back needs to include headers and data, as shown below:
/**
* 发送响应数据到客户端
*/
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());
}
Summarize
At this point, a handler that handles the upgrade of clear text from HTTP1.1 to HTTP2 is complete. Coupled with the support of the TLS extension protocol explained before, it constitutes a complete netty server that supports http2.
For examples in this article, please refer to: learn-netty4
This article has been included in http://www.flydean.com/27-netty-http2/
The most popular interpretation, the most profound dry goods, the most concise tutorial, and many tips you don't know are waiting for you to discover!
Welcome to pay attention to my official account: "Program those things", know technology, know you better!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。