diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index e20d14fd7c..c0968dfc73 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -6,6 +6,7 @@ sent to Trustin Lee . SVN Login(s) Name ------------------------------------------------------------------------------- +ataylor Andy Taylor trustin Trustin Heuiseung Lee ------------------------------------------------------------------------------- diff --git a/src/main/java/org/jboss/netty/example/http/HttpClient.java b/src/main/java/org/jboss/netty/example/http/HttpClient.java new file mode 100644 index 0000000000..71a423c64d --- /dev/null +++ b/src/main/java/org/jboss/netty/example/http/HttpClient.java @@ -0,0 +1,92 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.http; + +import java.net.InetSocketAddress; +import java.net.URI; +import java.util.concurrent.Executors; + +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; +import org.jboss.netty.handler.codec.http.DefaultHttpRequest; +import org.jboss.netty.handler.codec.http.HttpHeaders; +import org.jboss.netty.handler.codec.http.HttpMethod; +import org.jboss.netty.handler.codec.http.HttpRequest; +import org.jboss.netty.handler.codec.http.HttpVersion; +import org.jboss.netty.handler.codec.http.QueryStringEncoder; + +/** + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public class HttpClient { + public static void main(String[] args) throws Exception { + + // Parse options. + String host = "localhost"; + int port = 8080; + + // Configure the client. + ChannelFactory factory = + new NioClientSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool()); + + ClientBootstrap bootstrap = new ClientBootstrap(factory); + HttpPipelineFactory handler = new HttpPipelineFactory(new HttpResponseHandler()); + bootstrap.setPipelineFactory(handler); + bootstrap.setOption("tcpNoDelay", true); + bootstrap.setOption("keepAlive", true); + // Start the connection attempt. + ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)); + + // Wait until the connection attempt succeeds or fails. + Channel channel = future.awaitUninterruptibly().getChannel(); + if (!future.isSuccess()) { + future.getCause().printStackTrace(); + System.exit(0); + } + String message = "It's Hello From me"; + ChannelBuffer buf = ChannelBuffers.wrappedBuffer(message.getBytes()); + HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, new URI("/netty/")); + request.addHeader(HttpHeaders.HOST, host); + request.addHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(buf.writerIndex())); + request.setContent(buf); + ChannelFuture lastWriteFuture = channel.write(request); + buf = ChannelBuffers.wrappedBuffer(message.getBytes()); + QueryStringEncoder queryStringEncoder = new QueryStringEncoder("/netty/"); + queryStringEncoder.addParam("testparam", "hey ho"); + queryStringEncoder.addParam("testparam2", "hey ho again"); + request = new DefaultHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, queryStringEncoder.toUri()); + request.addHeader(HttpHeaders.HOST, host); + request.addHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(buf.writerIndex())); + request.setContent(buf); + lastWriteFuture = channel.write(request); + lastWriteFuture.awaitUninterruptibly(); + } +} diff --git a/src/main/java/org/jboss/netty/example/http/HttpPipelineFactory.java b/src/main/java/org/jboss/netty/example/http/HttpPipelineFactory.java new file mode 100644 index 0000000000..2e4427c8be --- /dev/null +++ b/src/main/java/org/jboss/netty/example/http/HttpPipelineFactory.java @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.http; + +import static org.jboss.netty.channel.Channels.*; + +import org.jboss.netty.channel.ChannelHandler; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.handler.codec.http.HttpRequestEncoder; +import org.jboss.netty.handler.codec.http.HttpResponseDecoder; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public class HttpPipelineFactory implements ChannelPipelineFactory { + private final ChannelHandler handler; + + public HttpPipelineFactory(HttpResponseHandler handler) { + this.handler = handler; + } + + public ChannelPipeline getPipeline() throws Exception { + // Create a default pipeline implementation. + ChannelPipeline pipeline = pipeline(); + pipeline.addLast("decoder", new HttpResponseDecoder()); + pipeline.addLast("encoder", new HttpRequestEncoder()); + pipeline.addLast("handler", handler); + return pipeline; + } +} diff --git a/src/main/java/org/jboss/netty/example/http/HttpRequestHandler.java b/src/main/java/org/jboss/netty/example/http/HttpRequestHandler.java new file mode 100644 index 0000000000..97aa7aaac7 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/http/HttpRequestHandler.java @@ -0,0 +1,67 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.http; + +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelPipelineCoverage; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.channel.SimpleChannelHandler; +import org.jboss.netty.handler.codec.http.DefaultHttpResponse; +import org.jboss.netty.handler.codec.http.HttpHeaders; +import org.jboss.netty.handler.codec.http.HttpRequest; +import org.jboss.netty.handler.codec.http.HttpResponse; +import org.jboss.netty.handler.codec.http.HttpResponseStatus; +import org.jboss.netty.handler.codec.http.HttpVersion; +import org.jboss.netty.handler.codec.http.QueryStringDecoder; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +@ChannelPipelineCoverage("all") +public class HttpRequestHandler extends SimpleChannelHandler { + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { + HttpRequest request = (HttpRequest) e.getMessage(); + System.out.println(request.getContent().toString(Charset.defaultCharset().name())); + QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getURI()); + Map> params = queryStringDecoder.getParameters(); + for (String key : params.keySet()) { + List vals = params.get(key); + for (String val : vals) { + System.out.println("param: " + key + "=" + val); + } + } + HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); + String message = "and its hello from me"; + ChannelBuffer buf = ChannelBuffers.wrappedBuffer(message.getBytes()); + response.setContent(buf); + response.addHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(buf.writerIndex())); + e.getChannel().write(response); + } +} diff --git a/src/main/java/org/jboss/netty/example/http/HttpResponseHandler.java b/src/main/java/org/jboss/netty/example/http/HttpResponseHandler.java new file mode 100644 index 0000000000..29c62dee42 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/http/HttpResponseHandler.java @@ -0,0 +1,43 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.http; + +import java.nio.charset.Charset; + +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelPipelineCoverage; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.channel.SimpleChannelHandler; +import org.jboss.netty.handler.codec.http.HttpResponse; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +@ChannelPipelineCoverage("all") +public class HttpResponseHandler extends SimpleChannelHandler { + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { + HttpResponse response = (HttpResponse) e.getMessage(); + System.out.println(response.getContent().toString(Charset.defaultCharset().name())); + } +} diff --git a/src/main/java/org/jboss/netty/example/http/HttpServer.java b/src/main/java/org/jboss/netty/example/http/HttpServer.java new file mode 100644 index 0000000000..46803bfb34 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/http/HttpServer.java @@ -0,0 +1,52 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.http; + +import java.net.InetSocketAddress; +import java.util.concurrent.Executors; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public class HttpServer { + public static void main(String[] args) { + // Configure the server. + ChannelFactory factory = + new NioServerSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool()); + + ServerBootstrap bootstrap = new ServerBootstrap(factory); + HttpServerPipelineFactory pipeline = new HttpServerPipelineFactory(new HttpRequestHandler()); + bootstrap.setPipelineFactory(pipeline); + bootstrap.setOption("child.tcpNoDelay", true); + bootstrap.setOption("child.keepAlive", true); + + // Bind and start to accept incoming connections. + bootstrap.bind(new InetSocketAddress(8080)); + } +} diff --git a/src/main/java/org/jboss/netty/example/http/HttpServerPipelineFactory.java b/src/main/java/org/jboss/netty/example/http/HttpServerPipelineFactory.java new file mode 100644 index 0000000000..a203c1c2bf --- /dev/null +++ b/src/main/java/org/jboss/netty/example/http/HttpServerPipelineFactory.java @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.http; + +import static org.jboss.netty.channel.Channels.*; + +import org.jboss.netty.channel.ChannelHandler; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.handler.codec.http.HttpRequestDecoder; +import org.jboss.netty.handler.codec.http.HttpResponseEncoder; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public class HttpServerPipelineFactory implements ChannelPipelineFactory { + private final ChannelHandler handler; + + public HttpServerPipelineFactory(HttpRequestHandler handler) { + this.handler = handler; + } + + public ChannelPipeline getPipeline() throws Exception { + // Create a default pipeline implementation. + ChannelPipeline pipeline = pipeline(); + pipeline.addLast("decoder", new HttpRequestDecoder()); + pipeline.addLast("encoder", new HttpResponseEncoder()); + pipeline.addLast("handler", handler); + return pipeline; + } +} diff --git a/src/main/java/org/jboss/netty/example/http/HttpWebserverClient.java b/src/main/java/org/jboss/netty/example/http/HttpWebserverClient.java new file mode 100644 index 0000000000..154cf81470 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/http/HttpWebserverClient.java @@ -0,0 +1,74 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.http; + +import java.net.InetSocketAddress; +import java.util.concurrent.Executors; + +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; +import org.jboss.netty.handler.codec.http.DefaultHttpRequest; +import org.jboss.netty.handler.codec.http.HttpHeaders; +import org.jboss.netty.handler.codec.http.HttpMethod; +import org.jboss.netty.handler.codec.http.HttpRequest; +import org.jboss.netty.handler.codec.http.HttpVersion; +import org.jboss.netty.handler.codec.http.QueryStringEncoder; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public class HttpWebserverClient { + public static void main(String[] args) throws Exception { + + // Parse options. + String host = "www.jboss.org"; + int port = 80; + + // Configure the client. + ChannelFactory factory = + new NioClientSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool()); + + ClientBootstrap bootstrap = new ClientBootstrap(factory); + HttpPipelineFactory handler = new HttpPipelineFactory(new HttpResponseHandler()); + bootstrap.setPipelineFactory(handler); + // Start the connection attempt. + ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)); + + // Wait until the connection attempt succeeds or fails. + Channel channel = future.awaitUninterruptibly().getChannel(); + if (!future.isSuccess()) { + future.getCause().printStackTrace(); + System.exit(0); + } + QueryStringEncoder uriBuilder = new QueryStringEncoder("/netty/"); + HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, uriBuilder.toUri()); + request.addHeader(HttpHeaders.HOST, host); + ChannelFuture lastWriteFuture = channel.write(request); + lastWriteFuture.awaitUninterruptibly(); + } +} \ No newline at end of file diff --git a/src/main/java/org/jboss/netty/handler/codec/http/DefaultHttpMessage.java b/src/main/java/org/jboss/netty/handler/codec/http/DefaultHttpMessage.java new file mode 100644 index 0000000000..c1a92c1d45 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/DefaultHttpMessage.java @@ -0,0 +1,126 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import org.jboss.netty.buffer.ChannelBuffer; + +/** + * a default Http Message which holds the headers and body. + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public class DefaultHttpMessage implements HttpMessage { + private final static Comparator caseIgnoringComparator = new CaseIgnoringComparator(); + + Map> headers = new TreeMap>(caseIgnoringComparator); + + private final HttpVersion version; + + private ChannelBuffer content; + + protected DefaultHttpMessage(final HttpVersion version) { + this.version = version; + } + + public void addHeader(final String name, final String value) { + if (value == null) { + throw new NullPointerException("value is null"); + } + if (headers.get(name) == null) { + headers.put(name, new ArrayList()); + } + headers.get(name).add(value); + } + + public void setHeader(final String name, final List values) { + if (values == null || values.size() == 0) { + throw new NullPointerException("no values present"); + } + headers.put(name, values); + } + + public int getContentLength() { + List contentLength = headers.get(HttpHeaders.CONTENT_LENGTH); + if (contentLength != null && contentLength.size() > 0) { + return Integer.valueOf(contentLength.get(0)); + } + return 0; + } + + public boolean isChunked() { + List chunked = headers.get(HttpHeaders.TRANSFER_ENCODING.KEY); + return chunked != null && chunked.size() > 0 && chunked.get(0).equalsIgnoreCase(HttpHeaders.TRANSFER_ENCODING.CHUNKED); + } + + public void clearHeaders() { + headers.clear(); + } + + public void setContent(final ChannelBuffer content) { + this.content = content; + } + + public String getHeader(final String name) { + List header = headers.get(name); + return header != null && header.size() > 0 ? headers.get(name).get(0) : null; + } + + public List getHeaders(final String name) { + return headers.get(name); + } + + public boolean containsHeader(final String name) { + return headers.containsKey(name); + } + + public Set getHeaderNames() { + return headers.keySet(); + } + + public HttpVersion getProtocolVersion() { + return version; + } + + public ChannelBuffer getContent() { + return content; + } + + private static class CaseIgnoringComparator implements Comparator { + + CaseIgnoringComparator() { + super(); + } + + public int compare(String o1, String o2) { + return o1.compareToIgnoreCase(o2); + } + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/DefaultHttpRequest.java b/src/main/java/org/jboss/netty/handler/codec/http/DefaultHttpRequest.java new file mode 100644 index 0000000000..4929ee10c1 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/DefaultHttpRequest.java @@ -0,0 +1,58 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import java.net.URI; + +/** + * An http request implementation + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public class DefaultHttpRequest extends DefaultHttpMessage implements HttpRequest { + + private final HttpMethod method; + + private final URI uri; + + public DefaultHttpRequest(HttpVersion httpVersion, HttpMethod method, URI uri) { + super(httpVersion); + this.method = method; + this.uri = uri; + } + + public HttpMethod getMethod() { + return method; + } + + public URI getURI() { + return uri; + } + + + public boolean isKeepAlive() { + //todo + return true; + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/DefaultHttpResponse.java b/src/main/java/org/jboss/netty/handler/codec/http/DefaultHttpResponse.java new file mode 100644 index 0000000000..0a9cc98b30 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/DefaultHttpResponse.java @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +/** + * an http response implementation + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public class DefaultHttpResponse extends DefaultHttpMessage implements HttpResponse { + private final HttpResponseStatus status; + + public DefaultHttpResponse(HttpVersion version, HttpResponseStatus status) { + super(version); + this.status = status; + } + + public HttpResponseStatus getStatus() { + return status; + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpCodecUtil.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpCodecUtil.java new file mode 100644 index 0000000000..f2065d0d8c --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpCodecUtil.java @@ -0,0 +1,59 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public class HttpCodecUtil { + //space ' ' + public static final byte SP = 32; + + //tab ' ' + public static final byte HT = 9; + + /** + * Carriage return + */ + public static final byte CR = 13; + + /** + * Equals '=' + */ + public static final byte EQUALS = 61; + + /** + * Line feed character + */ + public static final byte LF = 10; + + /** + * carriage return line feed + */ + public static final byte[] CRLF = new byte[] { CR, LF }; + + /** + * Colon ':' + */ + public static final byte COLON = 58; +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaders.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaders.java new file mode 100644 index 0000000000..98a4891f01 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaders.java @@ -0,0 +1,48 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public class HttpHeaders { + public static final String HOST = "Host"; + + public static final String CONTENT_LENGTH = "Content-Length"; + + public static final class CONNECTION { + public static final String KEY = "Connection"; + + public static final String CLOSE = "Close"; + + public static final String KEEP_ALIVE = "Keep-alive"; + } + + public static final class TRANSFER_ENCODING { + public static final String KEY = "Transfer-Encoding"; + + public static final String CHUNKED = "Chunked"; + } + + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpMessage.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpMessage.java new file mode 100644 index 0000000000..71b0a08002 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpMessage.java @@ -0,0 +1,60 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import java.util.List; +import java.util.Set; + +import org.jboss.netty.buffer.ChannelBuffer; + +/** + * Encapsulates an Http message. this will contain the protocol version, headers and the body of a message + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public interface HttpMessage { + String getHeader(String name); + + List getHeaders(String name); + + boolean containsHeader(String name); + + Set getHeaderNames(); + + HttpVersion getProtocolVersion(); + + ChannelBuffer getContent(); + + void addHeader(String name, String value); + + void setHeader(String name, List values); + + int getContentLength(); + + void setContent(ChannelBuffer content); + + boolean isChunked(); + + void clearHeaders(); +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpMessageDecoder.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpMessageDecoder.java new file mode 100644 index 0000000000..9177f72943 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpMessageDecoder.java @@ -0,0 +1,221 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import java.util.List; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.handler.codec.replay.ReplayingDecoder; + +/** + * Decodes an Http type message. + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public abstract class HttpMessageDecoder extends ReplayingDecoder { + protected HttpMessage message; + + private ChannelBuffer content; + + private int chunkSize; + + public enum ResponseState { + READ_INITIAL, + READ_HEADER, + READ_CONTENT, + READ_FIXED_LENGTH_CONTENT, + READ_CHUNK_SIZE, + READ_CHUNKED_CONTENT, + READ_CRLF,; + } + + private ResponseState nextState; + + protected HttpMessageDecoder() { + super(ResponseState.READ_INITIAL); + } + + @Override + protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, ResponseState state) throws Exception { + switch (state) { + case READ_INITIAL: { + readInitial(buffer); + } + case READ_HEADER: { + readHeaders(buffer); + //we return null here, this forces decode to be called again where we will decode the content + return null; + } + case READ_CONTENT: { + if (content == null) { + content = ChannelBuffers.dynamicBuffer(); + } + //this will cause a replay error until the channel is closed where this will read whats left in the buffer + content.writeBytes(buffer.readBytes(buffer.readableBytes())); + return reset(); + } + case READ_FIXED_LENGTH_CONTENT: { + //we have a content-length so we just read the correct number of bytes + readFixedLengthContent(buffer); + return reset(); + } + /** + * everything else after this point takes care of reading chunked content. basically, read chunk size, + * read chunk, read and ignore the CRLF and repeat until 0 + */ + case READ_CHUNK_SIZE: { + String line = readIntoCurrentLine(buffer); + + chunkSize = getChunkSize(line); + if (chunkSize == 0) { + byte next = buffer.readByte(); + if (next == HttpCodecUtil.CR) { + buffer.readByte(); + } + return reset(); + } + else { + checkpoint(ResponseState.READ_CHUNKED_CONTENT); + } + } + case READ_CHUNKED_CONTENT: { + readChunkedContent(buffer); + } + case READ_CRLF: { + byte next = buffer.readByte(); + if (next == HttpCodecUtil.CR) { + buffer.readByte(); + } + checkpoint(nextState); + return null; + } + default: { + throw new Error("Shouldn't reach here."); + } + + } + } + + private Object reset() { + message.setContent(content); + content = null; + nextState = null; + checkpoint(ResponseState.READ_INITIAL); + return message; + } + + private void readChunkedContent(ChannelBuffer buffer) { + if (content == null) { + content = ChannelBuffers.dynamicBuffer(chunkSize); + } + content.writeBytes(buffer, chunkSize); + nextState = ResponseState.READ_CHUNK_SIZE; + checkpoint(ResponseState.READ_CRLF); + } + + private void readFixedLengthContent(ChannelBuffer buffer) { + int length = message.getContentLength(); + if (content == null) { + content = ChannelBuffers.buffer(length); + } + content.writeBytes(buffer.readBytes(length)); + } + + private void readHeaders(ChannelBuffer buffer) { + message.clearHeaders(); + String line = readIntoCurrentLine(buffer); + String lastHeader = null; + while (!line.equals("")) { + if (line.startsWith(" ") || line.startsWith("\t")) { + List current = message.getHeaders(lastHeader); + int lastPos = current.size() - 1; + String newString = current.get(lastPos) + line.trim(); + current.remove(lastPos); + current.add(newString); + } + else { + String[] header = splitHeader(line); + message.addHeader(header[0], header[1]); + lastHeader = header[0]; + } + line = readIntoCurrentLine(buffer); + } + ResponseState nextState; + if (message.getContentLength() > 0) { + nextState = ResponseState.READ_FIXED_LENGTH_CONTENT; + } + else if (message.isChunked()) { + nextState = ResponseState.READ_CHUNK_SIZE; + } + else { + nextState = ResponseState.READ_CONTENT; + } + checkpoint(nextState); + } + + protected abstract void readInitial(ChannelBuffer buffer) throws Exception; + + private int getChunkSize(String hex) { + return Integer.valueOf(hex, 16); + } + + protected String readIntoCurrentLine(ChannelBuffer channel) { + StringBuffer sb = new StringBuffer(); + while (true) { + byte nextByte = channel.readByte(); + if (nextByte == HttpCodecUtil.CR) { + channel.readByte(); + return sb.toString(); + } + else if (nextByte == HttpCodecUtil.LF) { + return sb.toString(); + } + else { + sb.append((char) nextByte); + } + } + } + + protected String[] splitInitial(String sb) { + String[] split = sb.split(" "); + if (split.length != 3) { + throw new IllegalArgumentException(sb + "does not contain all 3 parts"); + } + return split; + } + + private String[] splitHeader(String sb) { + String[] split = sb.split(":", 2); + if (split.length != 2) { + throw new IllegalArgumentException(sb + "does not contain all 2 parts"); + } + for (int i = 0; i < split.length; i++) { + split[i] = split[i].trim(); + } + return split; + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpMessageEncoder.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpMessageEncoder.java new file mode 100644 index 0000000000..052587fb02 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpMessageEncoder.java @@ -0,0 +1,87 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import static org.jboss.netty.channel.Channels.*; +import static org.jboss.netty.handler.codec.http.HttpCodecUtil.*; + +import java.util.List; +import java.util.Set; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelPipelineCoverage; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.channel.SimpleChannelHandler; + +/** + * encodes an http message + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +@ChannelPipelineCoverage("one") +public abstract class HttpMessageEncoder extends SimpleChannelHandler { + @Override + public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception { + if (!(e.getMessage() instanceof HttpMessage)) { + ctx.sendDownstream(e); + return; + } + HttpMessage request = (HttpMessage) e.getMessage(); + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + encodeInitialLine(buf, request); + encodeHeaders(buf, request); + buf.writeBytes(CRLF); + if (request.getContent() != null) { + buf.writeBytes(request.getContent()); + } + write(ctx, e.getChannel(), e.getFuture(), buf, e.getRemoteAddress()); + } + + /** + * writes the headers + * Header1: value1 + * Header2: value2 + * + * @param buf + * @param message + */ + public void encodeHeaders(ChannelBuffer buf, HttpMessage message) { + Set headers = message.getHeaderNames(); + for (String header : headers) { + List values = message.getHeaders(header); + for (String value : values) { + + buf.writeBytes(header.getBytes()); + buf.writeByte(COLON); + buf.writeByte(SP); + buf.writeBytes(value.getBytes()); + buf.writeBytes(CRLF); + } + } + } + + protected abstract void encodeInitialLine(ChannelBuffer buf, HttpMessage message) throws Exception; +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpMethod.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpMethod.java new file mode 100644 index 0000000000..c5086a2382 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpMethod.java @@ -0,0 +1,87 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +/** + * This defines the methods available via a HTTP Request. + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public enum HttpMethod { + /** + * The OPTIONS method represents a request for information about the communication options available on the request/response + * chain identified by the Request-URI. This method allows the client to determine the options and/or requirements + * associated with a resource, or the capabilities of a server, without implying a resource action or initiating a + * resource retrieval. + */ + OPTIONS("OPTIONS"), + + /** + * The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. + * If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity + * in the response and not the source text of the process, unless that text happens to be the output of the process. + */ + GET("GET"), + + /** + * The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. + */ + HEAD("HEAD"), + + /** + * The POST method is used to request that the origin server accept the entity enclosed in the request as a new + * subordinate of the resource identified by the Request-URI in the Request-Line. + */ + POST("POST"), + + /** + * The PUT method requests that the enclosed entity be stored under the supplied Request-URI. + */ + PUT("PUT"), + + /** + * The DELETE method requests that the origin server delete the resource identified by the Request-URI. + */ + DELETE("DELETE"), + + /** + * The TRACE method is used to invoke a remote, application-layer loop- back of the request message. + */ + TRACE("TRACE"), + + /** + * This specification reserves the method name CONNECT for use with a proxy that can dynamically switch to being a tunnel + */ + CONNECT("CONNECT"),; + + private String method; + + + private HttpMethod(String method) { + this.method = method; + } + + public String getMethod() { + return method; + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpRequest.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpRequest.java new file mode 100644 index 0000000000..69efd98147 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpRequest.java @@ -0,0 +1,39 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import java.net.URI; + +/** + * An http request. + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public interface HttpRequest extends HttpMessage { + + boolean isKeepAlive(); + + HttpMethod getMethod(); + + URI getURI(); +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpRequestDecoder.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpRequestDecoder.java new file mode 100644 index 0000000000..c81dd48751 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpRequestDecoder.java @@ -0,0 +1,45 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import java.net.URI; + +import org.jboss.netty.buffer.ChannelBuffer; + +/** + * decodes an http request. + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public class HttpRequestDecoder extends HttpMessageDecoder { + + @Override + protected void readInitial(ChannelBuffer buffer) throws Exception{ + String line = readIntoCurrentLine(buffer); + checkpoint(ResponseState.READ_HEADER); + String[] split = splitInitial(line); + message = new DefaultHttpRequest(HttpVersion.getProtocol(split[2]), HttpMethod.valueOf(split[0]), new URI(split[1])); + + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpRequestEncoder.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpRequestEncoder.java new file mode 100644 index 0000000000..7a043a3a6a --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpRequestEncoder.java @@ -0,0 +1,54 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import static org.jboss.netty.handler.codec.http.HttpCodecUtil.*; + +import org.jboss.netty.buffer.ChannelBuffer; + +/** + * encodes an http request + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public class HttpRequestEncoder extends HttpMessageEncoder { + + /** + * writes the initial line i.e. 'GET /path/to/file/index.html HTTP/1.0' + * + * @param buf + * @param message + */ + @Override + protected void encodeInitialLine(ChannelBuffer buf, HttpMessage message) throws Exception { + HttpRequest request = (HttpRequest) message; + buf.writeBytes(request.getMethod().getMethod().getBytes()); + buf.writeByte(SP); + buf.writeBytes(request.getURI().toASCIIString().getBytes()); + buf.writeByte(SP); + buf.writeBytes(request.getProtocolVersion().value().getBytes()); + buf.writeBytes(CRLF); + } + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpResponse.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpResponse.java new file mode 100644 index 0000000000..00f1454e44 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpResponse.java @@ -0,0 +1,34 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + + +/** + * an http response. + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public interface HttpResponse extends HttpMessage { + HttpResponseStatus getStatus(); +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseDecoder.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseDecoder.java new file mode 100644 index 0000000000..b693cc0f54 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseDecoder.java @@ -0,0 +1,41 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import org.jboss.netty.buffer.ChannelBuffer; + +/** + * an http response decoder + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public class HttpResponseDecoder extends HttpMessageDecoder { + @Override + protected void readInitial(ChannelBuffer buffer) { + String line = readIntoCurrentLine(buffer); + checkpoint(ResponseState.READ_HEADER); + String[] split = splitInitial(line); + message = new DefaultHttpResponse(HttpVersion.getProtocol(split[0]), new HttpResponseStatus(Integer.valueOf(split[1]), split[2])); + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseEncoder.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseEncoder.java new file mode 100644 index 0000000000..bc9ee7d5d8 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseEncoder.java @@ -0,0 +1,46 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import static org.jboss.netty.handler.codec.http.HttpCodecUtil.*; + +import org.jboss.netty.buffer.ChannelBuffer; + +/** + * encodes an http response + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public class HttpResponseEncoder extends HttpMessageEncoder { + @Override + protected void encodeInitialLine(ChannelBuffer buf, HttpMessage message) { + HttpResponse response = (HttpResponse) message; + buf.writeBytes(response.getProtocolVersion().value().getBytes()); + buf.writeByte(SP); + buf.writeBytes(String.valueOf(response.getStatus().getCode()).getBytes()); + buf.writeByte(SP); + buf.writeBytes(String.valueOf(response.getStatus().getReasonPhrase()).getBytes()); + buf.writeBytes(CRLF); + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseStatus.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseStatus.java new file mode 100644 index 0000000000..a66f717ef9 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseStatus.java @@ -0,0 +1,131 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + + +/** + * The response codes and descriptions to return in the response. see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public class HttpResponseStatus { + + public static final HttpResponseStatus CONTINUE = new HttpResponseStatus(100, "Continue"); + + public static final HttpResponseStatus SWITCHING_PROTOCOLS = new HttpResponseStatus(101, "Switching Protocols"); + + public static final HttpResponseStatus OK = new HttpResponseStatus(200, "OK"); + + public static final HttpResponseStatus CREATED = new HttpResponseStatus(201, "Created"); + + public static final HttpResponseStatus ACCEPTED = new HttpResponseStatus(202, "Accepted"); + + public static final HttpResponseStatus NON_AUTHORITATIVE_INFORMATION = new HttpResponseStatus(203, "Non-Authoritative Information"); + + public static final HttpResponseStatus NO_CONTENT = new HttpResponseStatus(204, "No Content"); + + public static final HttpResponseStatus RESET_CONTENT = new HttpResponseStatus(205, "Reset Content"); + + public static final HttpResponseStatus PARTIAL_CONTENT = new HttpResponseStatus(206, "Partial Content"); + + public static final HttpResponseStatus MULTIPLE_CHOICES = new HttpResponseStatus(300, "Multiple Choices"); + + public static final HttpResponseStatus MOVED_PERMANENTLY = new HttpResponseStatus(301, "Moved Permanently"); + + public static final HttpResponseStatus FOUND = new HttpResponseStatus(302, "Found"); + + public static final HttpResponseStatus SEE_OTHER = new HttpResponseStatus(303, "See Other"); + + public static final HttpResponseStatus NOT_MODIFIED = new HttpResponseStatus(304, "Not Modified"); + + public static final HttpResponseStatus USE_PROXY = new HttpResponseStatus(305, "Use Proxy"); + + public static final HttpResponseStatus TEMPORARY_REDIRECT = new HttpResponseStatus(307, "Temporary Redirect"); + + public static final HttpResponseStatus BAD_REQUEST = new HttpResponseStatus(400, "Bad Request"); + + public static final HttpResponseStatus UNUATHORIZED = new HttpResponseStatus(401, "Unauthorized"); + + public static final HttpResponseStatus PAYMENT_REQUIRED = new HttpResponseStatus(402, "Payment Required"); + + public static final HttpResponseStatus FORBIDDEN = new HttpResponseStatus(403, "Forbidden"); + + public static final HttpResponseStatus NOT_FOUND = new HttpResponseStatus(404, "Not Found"); + + public static final HttpResponseStatus METHOD_NOT_ALLOWED = new HttpResponseStatus(405, "Method Not Allowed"); + + public static final HttpResponseStatus NOT_ACCEPTABLE = new HttpResponseStatus(406, "Not Acceptable"); + + public static final HttpResponseStatus PROXY_AUTHENTICATION_REQUIRED = new HttpResponseStatus(407, "Proxy Authentication Required"); + + public static final HttpResponseStatus REQUEST_TIMEOUT = new HttpResponseStatus(408, "Request Timeout"); + + public static final HttpResponseStatus CONFLICT = new HttpResponseStatus(409, "Conflict"); + + public static final HttpResponseStatus GONE = new HttpResponseStatus(410, "Gone"); + + public static final HttpResponseStatus LENGTH_REQUIRED = new HttpResponseStatus(411, "Length Required"); + + public static final HttpResponseStatus PRECONDITION_FAILED = new HttpResponseStatus(412, "Precondition Failed"); + + public static final HttpResponseStatus REQUEST_ENTITY_TOO_LARGE = new HttpResponseStatus(413, "Request Entity Too Large"); + + public static final HttpResponseStatus REQUEST_URI_TOO_LONG = new HttpResponseStatus(414, "Request-URI Too Long"); + + public static final HttpResponseStatus UNSUPPORTED_MEDIA_TYPE = new HttpResponseStatus(415, "Unsupported Media Type"); + + public static final HttpResponseStatus REQUESTED_RANGE_NOT_SATISFIABLE = new HttpResponseStatus(416, "Requested Range Not Satisfiable"); + + public static final HttpResponseStatus EXPECTATION_FAILED = new HttpResponseStatus(417, "Expectation Failed"); + + public static final HttpResponseStatus INTERNAL_SERVER_ERROR = new HttpResponseStatus(500, "Internal Server Error"); + + public static final HttpResponseStatus NOT_IMPLEMENTED = new HttpResponseStatus(501, "Not Implemented"); + + public static final HttpResponseStatus BAD_GATEWAY = new HttpResponseStatus(502, "Bad Gateway"); + + public static final HttpResponseStatus SERVICE_UNAVAILABLE = new HttpResponseStatus(503, "Service Unavailable"); + + public static final HttpResponseStatus GATEWAY_TIMEOUT = new HttpResponseStatus(504, "Gateway Timeout"); + + public static final HttpResponseStatus HTTP_VERSION_NOT_SUPPORTED = new HttpResponseStatus(505, "HTTP Version Not Supported"); + + + private final int code; + + private final String reasonPhrase; + + public HttpResponseStatus(int code, String reasonPhrase) { + this.code = code; + this.reasonPhrase = reasonPhrase; + } + + public int getCode() { + return code; + } + + public String getReasonPhrase() { + return reasonPhrase; + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpVersion.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpVersion.java new file mode 100644 index 0000000000..a1b7b2e59f --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpVersion.java @@ -0,0 +1,62 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +/** + * The protocols we support; + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) + */ +public enum HttpVersion { + HTTP_1_0("HTTP/1.0"), + + HTTP_1_1("HTTP/1.1"), + + UNKNOWN("UNKNOWN"),; + + private String version; + + private HttpVersion(String value) { + version = value; + } + + public String value() { + return version; + } + + public static HttpVersion getProtocol(String value) { + if (value == null) { + return UNKNOWN; + } + else if (value.equals(HTTP_1_0.value())) { + return HTTP_1_0; + } + else if (value.equals(HTTP_1_1.value())) { + return HTTP_1_1; + } + else { + return UNKNOWN; + } + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/QueryStringDecoder.java b/src/main/java/org/jboss/netty/handler/codec/http/QueryStringDecoder.java new file mode 100644 index 0000000000..01121c4d48 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/QueryStringDecoder.java @@ -0,0 +1,98 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public class QueryStringDecoder { + + private final String uri; + + private String path; + + private final Map> params = new HashMap>(); + + public QueryStringDecoder(String uri) { + this.uri = uri; + } + + public QueryStringDecoder(URI uri){ + this.uri = uri.toASCIIString(); + } + + public String getPath() { + //decode lazily + if(path == null) { + if(uri.contains("?")) { + decode(); + } + else { + path = uri; + } + } + return path; + } + + public Map> getParameters() { + if(path == null){ + if(uri.contains("?")) { + decode(); + } + else { + path = uri; + } + } + return params; + } + + private void decode() { + String[] split = uri.split("\\?", 2); + path = split[0]; + decodeParams(split[1]); + } + //todo - just replacing spaces at the minute, should we check for all characters or leave this to the user? + private void decodeParams(String s) { + String[] params = s.split("&"); + for (String param : params) { + String[] split = param.split("="); + String key = removeSpaceDelimeters(split[0]); + List values = this.params.get(key); + if(values == null) { + values = new ArrayList(); + this.params.put(key,values); + } + values.add(removeSpaceDelimeters(split[1])); + } + } + + private String removeSpaceDelimeters(String s) { + return s.replaceAll("%20", " "); + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/QueryStringEncoder.java b/src/main/java/org/jboss/netty/handler/codec/http/QueryStringEncoder.java new file mode 100644 index 0000000000..cc65744fed --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/QueryStringEncoder.java @@ -0,0 +1,84 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.handler.codec.http; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Andy Taylor (andy.taylor@jboss.org) + */ +public class QueryStringEncoder { + + final String url; + + final List params = new ArrayList(); + + public QueryStringEncoder(String url) { + this.url = url; + } + + public void addParam(String name, String value) { + if(name == null) { + throw new NullPointerException("name is null"); + } + if(value == null) { + throw new NullPointerException("value is null"); + } + params.add(new Param(name, value)); + } + + public URI toUri() throws URISyntaxException { + if (params.size() == 0) { + return new URI(url); + } + else { + StringBuffer sb = new StringBuffer(url).append("?"); + for (int i = 0; i < params.size(); i++) { + Param param = params.get(i); + sb.append(replaceSpaces(param.name)).append("=").append(replaceSpaces(param.value)); + if(i != params.size() - 1) { + sb.append("&"); + } + } + return new URI(sb.toString()); + } + } + + private String replaceSpaces(String s) { + return s.replaceAll(" ", "%20"); + } + + class Param { + final String name; + + final String value; + + public Param(String name, String value) { + this.value = value; + this.name = name; + } + } +}