From 04430cd6d3acea80a43e64ee3988548854476713 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Sun, 17 Oct 2010 18:34:03 +0000 Subject: [PATCH] Fixed issue: NETTY-359 Missing support for HTTP 'Expect: 100-continue' header. * Added HttpHeaders.is/set100ContinueExpected() * HttpMessageDecoder converts unchunked messages into chunked ones if Expect: 100-continue header exists. --- .../netty/handler/codec/http/HttpHeaders.java | 47 +++++++++++++++++++ .../codec/http/HttpMessageDecoder.java | 6 ++- 2 files changed, 51 insertions(+), 2 deletions(-) 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 index 777e5abbad..46d4517940 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaders.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaders.java @@ -674,6 +674,53 @@ public class HttpHeaders { message.setHeader(Names.HOST, value); } + /** + * Returns {@code true} if and only if the specified message contains the + * {@code "Expect: 100-continue"} header. + */ + public static boolean is100ContinueExpected(HttpMessage message) { + // In most cases, there will be one or zero 'Expect' header. + String value = message.getHeader(Names.EXPECT); + if (value == null) { + return false; + } + if (Values.CONTINUE.equalsIgnoreCase(value)) { + return true; + } + + // Multiple 'Expect' headers. Search through them. + for (String v: message.getHeaders(Names.EXPECT)) { + if (Values.CONTINUE.equalsIgnoreCase(v)) { + return true; + } + } + return false; + } + + /** + * Sets the {@code "Expect: 100-continue"} header to the specified message. + * If there is any existing {@code "Expect"} header, they are replaced with + * the new one. + */ + public static void set100ContinueExpected(HttpMessage message) { + set100ContinueExpected(message, true); + } + + /** + * Sets or removes the {@code "Expect: 100-continue"} header to / from the + * specified message. If the specified {@code value} is {@code true}, + * the {@code "Expect: 100-continue"} header is set and all other previous + * {@code "Expect"} headers are removed. Otherwise, all {@code "Expect"} + * headers are removed completely. + */ + public static void set100ContinueExpected(HttpMessage message, boolean set) { + if (set) { + message.setHeader(Names.EXPECT, Values.CONTINUE); + } else { + message.removeHeader(Names.EXPECT); + } + } + private static final int BUCKET_SIZE = 17; private static int hash(String name) { 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 7a80b91b22..75a4275d71 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 @@ -221,7 +221,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder maxChunkSize) { + if (contentLength > maxChunkSize || HttpHeaders.is100ContinueExpected(message)) { // Generate HttpMessage first. HttpChunks will follow. checkpoint(State.READ_FIXED_LENGTH_CONTENT_AS_CHUNKS); message.setChunked(true); @@ -232,13 +232,15 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder maxChunkSize) { + if (buffer.readableBytes() > maxChunkSize || HttpHeaders.is100ContinueExpected(message)) { // Generate HttpMessage first. HttpChunks will follow. checkpoint(State.READ_VARIABLE_LENGTH_CONTENT_AS_CHUNKS); message.setChunked(true); return message; } break; + default: + throw new IllegalStateException("Unexpected state: " + nextState); } } // We return null here, this forces decode to be called again where we will decode the content