Skip to content

Instantly share code, notes, and snippets.

@violetagg
Last active February 10, 2020 21:05
Show Gist options
  • Save violetagg/1b8d55276e3a00a5d153c6a5608a4251 to your computer and use it in GitHub Desktop.
Save violetagg/1b8d55276e3a00a5d153c6a5608a4251 to your computer and use it in GitHub Desktop.
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.DefaultLastHttpContent;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpServerUpgradeHandler;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http2.CleartextHttp2ServerUpgradeHandler;
import io.netty.handler.codec.http2.Http2FrameCodec;
import io.netty.handler.codec.http2.Http2FrameCodecBuilder;
import io.netty.handler.codec.http2.Http2MultiplexHandler;
import io.netty.handler.codec.http2.Http2ServerUpgradeCodec;
import io.netty.handler.codec.http2.Http2StreamFrameToHttpObjectCodec;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class TestServer {
public static void main(String[] args) throws Exception {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
EventLoopGroup group = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline()
.addLast(prepareCleartextHttp2ServerUpgradeHandler(executorService));
}
});
Channel ch = b.bind(8080)
.sync()
.channel();
ch.closeFuture()
.sync();
} finally {
group.shutdownGracefully();
executorService.shutdown();
}
}
private static CleartextHttp2ServerUpgradeHandler prepareCleartextHttp2ServerUpgradeHandler(
ScheduledExecutorService executorService) {
HttpServerCodec httpServerCodec = new HttpServerCodec();
Http2FrameCodec http2FrameCodec = Http2FrameCodecBuilder.forServer().build();
Http2MultiplexHandler multiplexHandler = prepareHttp2MultiplexHandler(executorService);
return new CleartextHttp2ServerUpgradeHandler(
httpServerCodec,
new HttpServerUpgradeHandler(
httpServerCodec,
protocol -> new Http2ServerUpgradeCodec(http2FrameCodec, multiplexHandler)),
new ChannelHandlerAdapter() {
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
ctx.pipeline()
.addAfter(ctx.name(), "Http2FrameCodec", http2FrameCodec)
.addAfter("Http2FrameCodec", "Http2MultiplexHandler", multiplexHandler)
.remove(this);
}
});
}
private static Http2MultiplexHandler prepareHttp2MultiplexHandler(ScheduledExecutorService executorService) {
return new Http2MultiplexHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline()
.addLast(
new Http2StreamFrameToHttpObjectCodec(true),
new ChannelDuplexHandler() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
executorService.schedule(() ->
ctx.writeAndFlush(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK))
.addListener(future -> {
ctx.write(new DefaultLastHttpContent(Unpooled.wrappedBuffer("last".getBytes())));
ctx.channel()
.eventLoop()
.execute(ctx::flush);
}), 500, TimeUnit.MILLISECONDS);
}
});
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment