From a5ebbfb1114d648e4ce9a199f795618fe9d9bf99 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Tue, 10 Mar 2009 07:53:15 +0000 Subject: [PATCH] * all limit parameters are mandatory to create HTTP decoders now for better security * chunks are not merged anymore for better security * modified HTTP client example to handle HTTP chunks --- .../http/HttpClientPipelineFactory.java | 2 +- .../example/http/HttpRequestHandler.java | 2 - .../example/http/HttpResponseHandler.java | 46 +++++++++++++-- .../codec/http/HttpMessageDecoder.java | 57 ++++++------------- .../codec/http/HttpRequestDecoder.java | 4 -- .../codec/http/HttpResponseDecoder.java | 4 -- 6 files changed, 59 insertions(+), 56 deletions(-) diff --git a/src/main/java/org/jboss/netty/example/http/HttpClientPipelineFactory.java b/src/main/java/org/jboss/netty/example/http/HttpClientPipelineFactory.java index e7e0c28fb2..04dc3498c6 100644 --- a/src/main/java/org/jboss/netty/example/http/HttpClientPipelineFactory.java +++ b/src/main/java/org/jboss/netty/example/http/HttpClientPipelineFactory.java @@ -43,7 +43,7 @@ public class HttpClientPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception { // Create a default pipeline implementation. ChannelPipeline pipeline = pipeline(); - pipeline.addLast("decoder", new HttpResponseDecoder()); + pipeline.addLast("decoder", new HttpResponseDecoder(8192, 8192, 8192)); 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 index f0213f640f..197d7a7ac1 100644 --- a/src/main/java/org/jboss/netty/example/http/HttpRequestHandler.java +++ b/src/main/java/org/jboss/netty/example/http/HttpRequestHandler.java @@ -93,7 +93,6 @@ public class HttpRequestHandler extends SimpleChannelHandler { if (request.isChunked()) { readingChunks = true; - return; } else { ChannelBuffer content = request.getContent(); if (content.readable()) { @@ -107,7 +106,6 @@ public class HttpRequestHandler extends SimpleChannelHandler { readingChunks = false; responseContent.append("END OF CONTENT\r\n"); writeResponse(e); - return; } else { responseContent.append("CHUNK: " + chunk.getContent().toString("UTF-8") + "\r\n"); } diff --git a/src/main/java/org/jboss/netty/example/http/HttpResponseHandler.java b/src/main/java/org/jboss/netty/example/http/HttpResponseHandler.java index 29c62dee42..15ee1c3a3d 100644 --- a/src/main/java/org/jboss/netty/example/http/HttpResponseHandler.java +++ b/src/main/java/org/jboss/netty/example/http/HttpResponseHandler.java @@ -21,23 +21,59 @@ */ package org.jboss.netty.example.http; -import java.nio.charset.Charset; - +import org.jboss.netty.buffer.ChannelBuffer; 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.HttpChunk; import org.jboss.netty.handler.codec.http.HttpResponse; /** * @author The Netty Project (netty-dev@lists.jboss.org) * @author Andy Taylor (andy.taylor@jboss.org) + * @author Trustin Lee (tlee@redhat.com) */ -@ChannelPipelineCoverage("all") +@ChannelPipelineCoverage("one") public class HttpResponseHandler extends SimpleChannelHandler { + + private volatile boolean readingChunks; + @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { - HttpResponse response = (HttpResponse) e.getMessage(); - System.out.println(response.getContent().toString(Charset.defaultCharset().name())); + if (!readingChunks) { + HttpResponse response = (HttpResponse) e.getMessage(); + + System.out.println("STATUS: " + response.getStatus()); + System.out.println("VERSION: " + response.getProtocolVersion()); + System.out.println(); + + if (!response.getHeaderNames().isEmpty()) { + for (String name: response.getHeaderNames()) { + for (String value: response.getHeaders(name)) { + System.out.println("HEADER: " + name + " = " + value); + } + } + System.out.println(); + } + + if (response.getStatus().getCode() == 200 && response.isChunked()) { + readingChunks = true; + System.out.println("CHUNKED CONTENT:"); + } else { + ChannelBuffer content = response.getContent(); + if (content.readable()) { + System.out.println("CONTENT:"); + System.out.println(content.toString("UTF-8")); + } + } + } else { + HttpChunk chunk = (HttpChunk) e.getMessage(); + if (chunk.isLast()) { + readingChunks = false; + } else { + System.out.println(chunk.getContent().toString("UTF-8")); + } + } } } 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 index dd29486024..18ff65b3d4 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/HttpMessageDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpMessageDecoder.java @@ -77,10 +77,6 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder 0; - } - @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, State state) throws Exception { switch (state) { @@ -135,12 +127,8 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder maxChunkSize && nextState == State.READ_FIXED_LENGTH_CONTENT) { + switch (nextState) { + case READ_FIXED_LENGTH_CONTENT: + if (contentLength > maxChunkSize) { // Generate HttpMessage first. HttpChunks will follow. checkpoint(State.READ_FIXED_LENGTH_CONTENT_AS_CHUNKS); message.addHeader(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED); @@ -159,12 +146,16 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder maxChunkSize) { // Generate HttpMessage first. HttpChunks will follow. checkpoint(State.READ_VARIABLE_LENGTH_CONTENT_AS_CHUNKS); message.addHeader(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED); return message; } + break; } } // We return null here, this forces decode to be called again where we will decode the content @@ -231,31 +222,17 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder maxChunkSize) { + // A chunk is too large. Split them into multiple chunks again. + checkpoint(State.READ_CHUNKED_CONTENT_AS_CHUNKS); } else { checkpoint(State.READ_CHUNKED_CONTENT); } } case READ_CHUNKED_CONTENT: { - if (canGenerateChunks()) { - HttpChunk chunk = new DefaultHttpChunk(buffer.readBytes(chunkSize)); - checkpoint(State.READ_CHUNK_DELIMITER); - return chunk; - } else { - if (content == null) { - content = ChannelBuffers.dynamicBuffer( - chunkSize, channel.getConfig().getBufferFactory()); - } - content.writeBytes(buffer, chunkSize); - checkpoint(State.READ_CHUNK_DELIMITER); - return null; - } + HttpChunk chunk = new DefaultHttpChunk(buffer.readBytes(chunkSize)); + checkpoint(State.READ_CHUNK_DELIMITER); + return chunk; } case READ_CHUNKED_CONTENT_AS_CHUNKS: { int chunkSize = this.chunkSize; 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 index 6ca62d52d9..9f6bf665b2 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/HttpRequestDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpRequestDecoder.java @@ -32,10 +32,6 @@ package org.jboss.netty.handler.codec.http; */ public class HttpRequestDecoder extends HttpMessageDecoder { - public HttpRequestDecoder() { - super(); - } - public HttpRequestDecoder( int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) { super(maxInitialLineLength, maxHeaderSize, maxChunkSize); 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 index 740042e3f2..baaa49b35e 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpResponseDecoder.java @@ -32,10 +32,6 @@ package org.jboss.netty.handler.codec.http; */ public class HttpResponseDecoder extends HttpMessageDecoder { - public HttpResponseDecoder() { - super(); - } - public HttpResponseDecoder( int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) { super(maxInitialLineLength, maxHeaderSize, maxChunkSize);