Fixed issue: NETTY-359 Missing support for HTTP 'Expect: 100-continue' header.

* Improved HttpHeaders.is100ContinueExpected() to conform to the RFC
* HttpChunkAggregator now sends "HTTP/1.1 100 Continue" response automatically.
* Added some TODO items which should be done in 4.0.
This commit is contained in:
Trustin Lee 2010-10-19 05:40:44 +00:00
parent d093ed4a54
commit 57dc0b3bc8
3 changed files with 39 additions and 0 deletions

View File

@ -15,6 +15,9 @@
*/
package org.jboss.netty.handler.codec.http;
import static org.jboss.netty.channel.Channels.*;
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
import java.util.List;
import java.util.Map.Entry;
@ -27,6 +30,7 @@ import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.frame.TooLongFrameException;
import org.jboss.netty.util.CharsetUtil;
/**
* A {@link ChannelHandler} that aggregates an {@link HttpMessage}
@ -53,6 +57,9 @@ import org.jboss.netty.handler.codec.frame.TooLongFrameException;
*/
public class HttpChunkAggregator extends SimpleChannelUpstreamHandler {
private static final ChannelBuffer CONTINUE = ChannelBuffers.copiedBuffer(
"HTTP/1.1 100 Continue\r\n\r\n", CharsetUtil.US_ASCII);
private final int maxContentLength;
private HttpMessage currentMessage;
@ -82,6 +89,16 @@ public class HttpChunkAggregator extends SimpleChannelUpstreamHandler {
if (msg instanceof HttpMessage) {
HttpMessage m = (HttpMessage) msg;
// Handle the 'Expect: 100-continue' header if necessary.
// TODO: Respond with 413 Request Entity Too Large
// and discard the traffic or close the connection.
// No need to notify the upstream handlers - just log.
// If decoding a response, just throw an exception.
if (is100ContinueExpected(m)) {
write(ctx, succeededFuture(ctx.getChannel()), CONTINUE.duplicate());
}
if (m.isChunked()) {
// A chunked message - remove 'Transfer-Encoding' header,
// initialize the cumulative buffer, and wait for incoming chunks.
@ -111,6 +128,10 @@ public class HttpChunkAggregator extends SimpleChannelUpstreamHandler {
ChannelBuffer content = currentMessage.getContent();
if (content.readableBytes() > maxContentLength - chunk.getContent().readableBytes()) {
// TODO: Respond with 413 Request Entity Too Large
// and discard the traffic or close the connection.
// No need to notify the upstream handlers - just log.
// If decoding a response, just throw an exception.
throw new TooLongFrameException(
"HTTP content length exceeded " + maxContentLength +
" bytes.");

View File

@ -679,6 +679,16 @@ public class HttpHeaders {
* {@code "Expect: 100-continue"} header.
*/
public static boolean is100ContinueExpected(HttpMessage message) {
// Expect: 100-continue is for requests only.
if (!(message instanceof HttpRequest)) {
return false;
}
// It works only on HTTP/1.1 or later.
if (message.getProtocolVersion().compareTo(HttpVersion.HTTP_1_1) < 0) {
return false;
}
// In most cases, there will be one or zero 'Expect' header.
String value = message.getHeader(Names.EXPECT);
if (value == null) {

View File

@ -536,6 +536,10 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
// Abort decoding if the header part is too large.
if (headerSize >= maxHeaderSize) {
// TODO: Respond with Bad Request and discard the traffic
// or close the connection.
// No need to notify the upstream handlers - just log.
// If decoding a response, just throw an exception.
throw new TooLongFrameException(
"HTTP header is larger than " +
maxHeaderSize + " bytes.");
@ -581,6 +585,10 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
}
else {
if (lineLength >= maxLineLength) {
// TODO: Respond with Bad Request and discard the traffic
// or close the connection.
// No need to notify the upstream handlers - just log.
// If decoding a response, just throw an exception.
throw new TooLongFrameException(
"An HTTP line is larger than " + maxLineLength +
" bytes.");