2015-01-06

Netty 4 HTTP Hello World

Intro

Finding examples for netty took me a lot of time. Most of the time writing even the smallest portions of code requires you to go trough multiple sources ranging from youtube videos to official netty documentation. In this post I'll show you how to build a basic netty http hello world example. You probably won't have any trouble to continue and write your own app from here.

Dependencies

This example has just one dependency
http://mvnrepository.com/artifact/io.netty/netty-all/4.0.24.Final.

Setting Netty up

Create a class with a name of your choosing it doesn't really matter. This is a hello world example so I suggest writing a main method to run the example. We'll run the example on http port 80:

    public static void main(String[] args) 
        throws InterruptedException {

        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 200)
                .childOption(ChannelOption.ALLOCATOR,
                    PooledByteBufAllocator.DEFAULT)
                .childHandler(
                        new ChannelInitializer<SocketChannel>() {
                            @Override
                            public void initChannel(
                                SocketChannel ch) throws Exception {
                                ChannelPipeline p = ch.pipeline();
                                p.addLast(new HttpRequestDecoder());
                                p.addLast(new HttpResponseEncoder());
                                p.addLast(new MySuperHttpHandler());
                            }
                        });

            ChannelFuture future = bootstrap.bind(80).sync();

            future.channel().closeFuture().sync();

        }
        finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();

            bossGroup.terminationFuture().sync();
            workerGroup.terminationFuture().sync();
        }

    }
    

Hello World HTTP Handler

    public class MySuperHttpHandler extends 
            SimpleChannelInboundHandler<Object> {
            private static final byte[] CONTENT = 
                {'H', 'E', 'L', 'L', 'O'};

            @Override
            public void channelReadComplete(
                ChannelHandlerContext ctx) {

                ctx.flush();
            }

            @Override
            public void channelRead0(ChannelHandlerContext ctx,
                    Object msg) {

                if (msg instanceof HttpRequest) {
                    HttpRequest req = (HttpRequest) msg;

                    String reqUrl = req.getUri();

                    System.out.println(reqUrl);

                    // do something further with request here ...

                    // this is the response part
                    if (HttpHeaders.is100ContinueExpected(req)) {
                        ctx.write(new DefaultFullHttpResponse(
                            HttpVersion.HTTP_1_1, 
                            HttpResponseStatus.CONTINUE));
                    }

                    boolean keepAlive = HttpHeaders.isKeepAlive(req);
                    FullHttpResponse response = 
                        new DefaultFullHttpResponse(
                            HttpVersion.HTTP_1_1,
                            HttpResponseStatus.OK,
                            Unpooled.wrappedBuffer(CONTENT));

                    response.headers().set(
                        HttpHeaders.Names.CONTENT_TYPE, "text/plain");
                    response.headers().set(
                        HttpHeaders.Names.CONTENT_LENGTH,
                        response.content().readableBytes());

                    if (!keepAlive) {
                        ctx.write(response)
                            .addListener(ChannelFutureListener.CLOSE);
                    } else {
                        response.headers().set(
                            HttpHeaders.Names.CONNECTION,
                            HttpHeaders.Values.KEEP_ALIVE);

                        ctx.write(response);
                    }
                }
            }

            @Override
            public void exceptionCaught(
                ChannelHandlerContext ctx, Throwable cause) {
                ctx.close();
            }
    }
    

No comments: