diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectEncoder.java index 4a5a1c93c1..973e92480f 100755 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectEncoder.java @@ -91,12 +91,6 @@ public abstract class HttpObjectEncoder extends MessageTo switch (state) { case ST_INIT: throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg)); - case ST_CONTENT_ALWAYS_EMPTY: - out.add(EMPTY_BUFFER); - if (msg instanceof LastHttpContent) { - state = ST_INIT; - } - return; case ST_CONTENT_NON_CHUNK: final long contentLength = contentLength(msg); if (contentLength > 0) { @@ -110,33 +104,43 @@ public abstract class HttpObjectEncoder extends MessageTo } out.add(encodeAndRetain(msg)); } - } else { - if (buf != null) { - out.add(buf); - } else { - // Need to produce some output otherwise an - // IllegalStateException will be thrown - out.add(EMPTY_BUFFER); + + if (msg instanceof LastHttpContent) { + state = ST_INIT; } + + break; + } + // fall-through! + case ST_CONTENT_ALWAYS_EMPTY: + + if (buf != null) { + // We allocated a buffer so add it now. + out.add(buf); + } else { + // Need to produce some output otherwise an + // IllegalStateException will be thrown + out.add(EMPTY_BUFFER); } - if (msg instanceof LastHttpContent) { - state = ST_INIT; - } - return; + break; case ST_CONTENT_CHUNK: if (buf != null) { + // We allocated a buffer so add it now. out.add(buf); } encodeChunkedContent(ctx, msg, contentLength(msg), out); - return; + + break; default: throw new Error(); } - } else { - if (buf != null) { - out.add(buf); + + if (msg instanceof LastHttpContent) { + state = ST_INIT; } + } else if (buf != null) { + out.add(buf); } } @@ -169,14 +173,10 @@ public abstract class HttpObjectEncoder extends MessageTo buf.writeBytes(CRLF); out.add(buf); } - - state = ST_INIT; - } else { - if (contentLength == 0) { - // Need to produce some output otherwise an - // IllegalstateException will be thrown - out.add(EMPTY_BUFFER); - } + } else if (contentLength == 0) { + // Need to produce some output otherwise an + // IllegalstateException will be thrown + out.add(EMPTY_BUFFER); } } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java index b207b6d3d7..c53818ec41 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java @@ -145,6 +145,32 @@ public class HttpServerCodecTest { assertFalse(ch.finishAndReleaseAll()); } + @Test + public void testChunkedHeadFullHttpResponse() { + EmbeddedChannel ch = new EmbeddedChannel(new HttpServerCodec()); + + // Send the request headers. + assertTrue(ch.writeInbound(Unpooled.copiedBuffer( + "HEAD / HTTP/1.1\r\n\r\n", CharsetUtil.UTF_8))); + + HttpRequest request = ch.readInbound(); + assertEquals(HttpMethod.HEAD, request.method()); + LastHttpContent content = ch.readInbound(); + assertFalse(content.content().isReadable()); + content.release(); + + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); + HttpUtil.setTransferEncodingChunked(response, true); + assertTrue(ch.writeOutbound(response)); + assertTrue(ch.finish()); + + ByteBuf buf = ch.readOutbound(); + assertEquals("HTTP/1.1 200 OK\r\ntransfer-encoding: chunked\r\n\r\n", buf.toString(CharsetUtil.US_ASCII)); + buf.release(); + + assertFalse(ch.finishAndReleaseAll()); + } + private static ByteBuf prepareDataChunk(int size) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < size; ++i) {