diff --git a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServer.java b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServer.java new file mode 100644 index 0000000000..9710600a53 --- /dev/null +++ b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServer.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.example.http.helloworld; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +/** + * An HTTP server that sends back the content of the received HTTP request + * in a pretty plaintext form. + */ +public class HttpHelloWorldServer { + + private final int port; + + public HttpHelloWorldServer(int port) { + this.port = port; + } + + public void run() throws Exception { + // Configure the server. + EventLoopGroup bossGroup = new NioEventLoopGroup(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + try { + ServerBootstrap b = new ServerBootstrap(); + b.option(ChannelOption.SO_BACKLOG, 1024); + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .childHandler(new HttpHelloWorldServerInitializer()); + + Channel ch = b.bind(port).sync().channel(); + ch.closeFuture().sync(); + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + public static void main(String[] args) throws Exception { + int port; + if (args.length > 0) { + port = Integer.parseInt(args[0]); + } else { + port = 8080; + } + new HttpHelloWorldServer(port).run(); + } +} diff --git a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java new file mode 100644 index 0000000000..3f0c0b4338 --- /dev/null +++ b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.example.http.helloworld; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.MessageList; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.util.CharsetUtil; + + +import static io.netty.handler.codec.http.HttpHeaders.Names.*; +import static io.netty.handler.codec.http.HttpHeaders.*; +import static io.netty.handler.codec.http.HttpResponseStatus.*; +import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; + +public class HttpHelloWorldServerHandler extends ChannelInboundHandlerAdapter { + private static final ByteBuf CONTENT = + Unpooled.unreleasableBuffer(Unpooled.buffer().writeBytes("Hello World".getBytes(CharsetUtil.US_ASCII))); + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageList msgs) throws Exception { + MessageList out = MessageList.newInstance(); + for (int i = 0; i < msgs.size(); i++) { + Object msg = msgs.get(i); + if (msg instanceof HttpRequest) { + HttpRequest req = (HttpRequest) msg; + + if (is100ContinueExpected(req)) { + out.add(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE)); + } + boolean keepAlive = isKeepAlive(req); + FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, CONTENT.duplicate()); + response.headers().set(CONTENT_TYPE, "text/plain"); + response.headers().set(CONTENT_LENGTH, response.content().readableBytes()); + + if (!keepAlive) { + out.add(response); + ctx.write(out).addListener(ChannelFutureListener.CLOSE); + out = MessageList.newInstance(); + } else { + out.add(response); + response.headers().set(CONNECTION, Values.KEEP_ALIVE); + } + } + } + ctx.write(out); + msgs.releaseAllAndRecycle(); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + cause.printStackTrace(); + ctx.close(); + } +} diff --git a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerInitializer.java b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerInitializer.java new file mode 100644 index 0000000000..a1c6bbeaa3 --- /dev/null +++ b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerInitializer.java @@ -0,0 +1,31 @@ +/* + * Copyright 2013 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.example.http.helloworld; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.HttpServerCodec; + +public class HttpHelloWorldServerInitializer extends ChannelInitializer { + @Override + public void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline p = ch.pipeline(); + + p.addLast("codec", new HttpServerCodec()); + p.addLast("handler", new HttpHelloWorldServerHandler()); + } +}