1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.example.http2.helloworld.server;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.ByteBufUtil;
20 import io.netty.channel.ChannelHandlerContext;
21 import io.netty.handler.codec.http.FullHttpRequest;
22 import io.netty.handler.codec.http.HttpHeaderNames;
23 import io.netty.handler.codec.http.HttpMethod;
24 import io.netty.handler.codec.http.HttpScheme;
25 import io.netty.handler.codec.http.HttpServerUpgradeHandler;
26 import io.netty.handler.codec.http2.DefaultHttp2Headers;
27 import io.netty.handler.codec.http2.Http2ConnectionDecoder;
28 import io.netty.handler.codec.http2.Http2ConnectionEncoder;
29 import io.netty.handler.codec.http2.Http2ConnectionHandler;
30 import io.netty.handler.codec.http2.Http2Flags;
31 import io.netty.handler.codec.http2.Http2FrameListener;
32 import io.netty.handler.codec.http2.Http2Headers;
33 import io.netty.handler.codec.http2.Http2Settings;
34 import io.netty.util.CharsetUtil;
35
36 import static io.netty.buffer.Unpooled.copiedBuffer;
37 import static io.netty.buffer.Unpooled.unreleasableBuffer;
38 import static io.netty.handler.codec.http.HttpResponseStatus.OK;
39
40
41
42
43 public final class HelloWorldHttp2Handler extends Http2ConnectionHandler implements Http2FrameListener {
44
45 static final ByteBuf RESPONSE_BYTES = unreleasableBuffer(
46 copiedBuffer("Hello World", CharsetUtil.UTF_8)).asReadOnly();
47
48 HelloWorldHttp2Handler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
49 Http2Settings initialSettings) {
50 super(decoder, encoder, initialSettings);
51 }
52
53 private static Http2Headers http1HeadersToHttp2Headers(FullHttpRequest request) {
54 CharSequence host = request.headers().get(HttpHeaderNames.HOST);
55 Http2Headers http2Headers = new DefaultHttp2Headers()
56 .method(HttpMethod.GET.asciiName())
57 .path(request.uri())
58 .scheme(HttpScheme.HTTP.name());
59 if (host != null) {
60 http2Headers.authority(host);
61 }
62 return http2Headers;
63 }
64
65
66
67
68
69 @Override
70 public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
71 if (evt instanceof HttpServerUpgradeHandler.UpgradeEvent) {
72 HttpServerUpgradeHandler.UpgradeEvent upgradeEvent =
73 (HttpServerUpgradeHandler.UpgradeEvent) evt;
74 onHeadersRead(ctx, 1, http1HeadersToHttp2Headers(upgradeEvent.upgradeRequest()), 0 , true);
75 }
76 super.userEventTriggered(ctx, evt);
77 }
78
79 @Override
80 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
81 super.exceptionCaught(ctx, cause);
82 cause.printStackTrace();
83 ctx.close();
84 }
85
86
87
88
89 private void sendResponse(ChannelHandlerContext ctx, int streamId, ByteBuf payload) {
90
91 Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText());
92 encoder().writeHeaders(ctx, streamId, headers, 0, false, ctx.newPromise());
93 encoder().writeData(ctx, streamId, payload, 0, true, ctx.newPromise());
94
95
96 }
97
98 @Override
99 public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding, boolean endOfStream) {
100 int processed = data.readableBytes() + padding;
101 if (endOfStream) {
102 sendResponse(ctx, streamId, data.retain());
103 }
104 return processed;
105 }
106
107 @Override
108 public void onHeadersRead(ChannelHandlerContext ctx, int streamId,
109 Http2Headers headers, int padding, boolean endOfStream) {
110 if (endOfStream) {
111 ByteBuf content = ctx.alloc().buffer();
112 content.writeBytes(RESPONSE_BYTES.duplicate());
113 ByteBufUtil.writeAscii(content, " - via HTTP/2");
114 sendResponse(ctx, streamId, content);
115 }
116 }
117
118 @Override
119 public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency,
120 short weight, boolean exclusive, int padding, boolean endOfStream) {
121 onHeadersRead(ctx, streamId, headers, padding, endOfStream);
122 }
123
124 @Override
125 public void onPriorityRead(ChannelHandlerContext ctx, int streamId, int streamDependency,
126 short weight, boolean exclusive) {
127 }
128
129 @Override
130 public void onRstStreamRead(ChannelHandlerContext ctx, int streamId, long errorCode) {
131 }
132
133 @Override
134 public void onSettingsAckRead(ChannelHandlerContext ctx) {
135 }
136
137 @Override
138 public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) {
139 }
140
141 @Override
142 public void onPingRead(ChannelHandlerContext ctx, long data) {
143 }
144
145 @Override
146 public void onPingAckRead(ChannelHandlerContext ctx, long data) {
147 }
148
149 @Override
150 public void onPushPromiseRead(ChannelHandlerContext ctx, int streamId, int promisedStreamId,
151 Http2Headers headers, int padding) {
152 }
153
154 @Override
155 public void onGoAwayRead(ChannelHandlerContext ctx, int lastStreamId, long errorCode, ByteBuf debugData) {
156 }
157
158 @Override
159 public void onWindowUpdateRead(ChannelHandlerContext ctx, int streamId, int windowSizeIncrement) {
160 }
161
162 @Override
163 public void onUnknownFrame(ChannelHandlerContext ctx, byte frameType, int streamId,
164 Http2Flags flags, ByteBuf payload) {
165 }
166 }