Created
February 22, 2014 18:32
-
-
Save mnadel/9159626 to your computer and use it in GitHub Desktop.
Netty HTTP Server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import io.netty.buffer.Unpooled; | |
import io.netty.channel.ChannelFutureListener; | |
import io.netty.channel.ChannelHandlerAdapter; | |
import io.netty.channel.ChannelHandlerContext; | |
import io.netty.channel.ChannelInboundHandlerAdapter; | |
import io.netty.handler.codec.http.*; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import java.nio.charset.Charset; | |
import static io.netty.handler.codec.http.HttpHeaders.Names.*; | |
import static io.netty.handler.codec.http.HttpHeaders.is100ContinueExpected; | |
import static io.netty.handler.codec.http.HttpHeaders.isKeepAlive; | |
import static io.netty.handler.codec.http.HttpResponseStatus.CONTINUE; | |
import static io.netty.handler.codec.http.HttpResponseStatus.OK; | |
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; | |
public class RequestHandler extends ChannelInboundHandlerAdapter { | |
private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); | |
private static final Charset UTF8 = Charset.forName("UTF-8"); | |
public RequestHandler() { | |
log.trace("Created handler: {}", this.hashCode()); | |
} | |
@Override | |
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { | |
log.trace("Handler {} got: {}", this.hashCode(), msg.getClass()); | |
if (msg instanceof DefaultHttpRequest) { | |
HttpRequest req = (DefaultHttpRequest) msg; | |
log.debug("Got request: {}", msg); | |
if (is100ContinueExpected(req)) { | |
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE)); | |
} | |
String resp = "Hello world!"; | |
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(resp.getBytes(UTF8))); | |
res.headers().set(CONTENT_TYPE, "text/plain"); | |
res.headers().set(CONTENT_LENGTH, res.content().readableBytes()); | |
if (isKeepAlive(req)) { | |
res.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE); | |
ctx.write(res); | |
} else { | |
ctx.write(res).addListener(ChannelFutureListener.CLOSE); | |
} | |
} | |
} | |
@Override | |
public void channelReadComplete(ChannelHandlerContext ctx) { | |
ctx.flush(); | |
} | |
@Override | |
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { | |
log.error("Crap!", cause); | |
ctx.close(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import io.netty.bootstrap.ServerBootstrap; | |
import io.netty.channel.ChannelFuture; | |
import io.netty.channel.ChannelInitializer; | |
import io.netty.channel.ChannelOption; | |
import io.netty.channel.EventLoopGroup; | |
import io.netty.channel.nio.NioEventLoopGroup; | |
import io.netty.channel.socket.SocketChannel; | |
import io.netty.channel.socket.nio.NioServerSocketChannel; | |
import io.netty.handler.codec.http.HttpServerCodec; | |
import org.apache.commons.cli.CommandLine; | |
import org.apache.commons.cli.CommandLineParser; | |
import org.apache.commons.cli.GnuParser; | |
import org.apache.commons.cli.Options; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
public class Server { | |
private static final Logger log = LoggerFactory.getLogger(Server.class); | |
private int port; | |
public Server(int port) { | |
this.port = port; | |
} | |
public void run() throws Exception { | |
EventLoopGroup masterGroup = new NioEventLoopGroup(); | |
EventLoopGroup workerGroup = new NioEventLoopGroup(); | |
try { | |
ServerBootstrap b = new ServerBootstrap(); | |
b.group(masterGroup, workerGroup) | |
.channel(NioServerSocketChannel.class) | |
.childHandler(new ChannelInitializer<SocketChannel>() { | |
@Override | |
public void initChannel(SocketChannel ch) throws Exception { | |
ch.pipeline().addLast("codec", new HttpServerCodec()); | |
ch.pipeline().addLast("handler", new RequestHandler()); | |
} | |
}) | |
.option(ChannelOption.SO_BACKLOG, 128) | |
.childOption(ChannelOption.SO_KEEPALIVE, true); | |
ChannelFuture f = b.bind(port).sync(); | |
f.channel().closeFuture().sync(); | |
} finally { | |
workerGroup.shutdownGracefully(); | |
masterGroup.shutdownGracefully(); | |
} | |
} | |
public static void main(String[] args) throws Exception { | |
Options opts = new Options(); | |
opts.addOption("p", "port", true, "Listen port (default: 8080)"); | |
CommandLineParser parser = new GnuParser(); | |
CommandLine cmd = parser.parse(opts, args); | |
int port = Integer.parseInt(cmd.getOptionValue("port", "8080")); | |
new Server(port).run(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment