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 e225f7c2e0..7ebfd10782 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 @@ -21,6 +21,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.FileRegion; import io.netty.handler.codec.MessageToMessageEncoder; import io.netty.util.CharsetUtil; +import io.netty.util.ReferenceCountUtil; import io.netty.util.internal.StringUtil; import java.util.Iterator; @@ -109,10 +110,12 @@ public abstract class HttpObjectEncoder extends MessageTo // ch.write(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); // // See https://github.com/netty/netty/issues/2983 for more information. - - if (msg instanceof ByteBuf && !((ByteBuf) msg).isReadable()) { - out.add(EMPTY_BUFFER); - return; + if (msg instanceof ByteBuf) { + final ByteBuf potentialEmptyBuf = (ByteBuf) msg; + if (!potentialEmptyBuf.isReadable()) { + out.add(potentialEmptyBuf.retain()); + return; + } } if (msg instanceof HttpContent || msg instanceof ByteBuf || msg instanceof FileRegion) { @@ -210,7 +213,7 @@ public abstract class HttpObjectEncoder extends MessageTo } else if (contentLength == 0) { // Need to produce some output otherwise an // IllegalStateException will be thrown - out.add(EMPTY_BUFFER); + out.add(ReferenceCountUtil.retain(msg)); } } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestEncoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestEncoderTest.java index 548566b24b..6a2ad13e60 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestEncoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestEncoderTest.java @@ -17,13 +17,20 @@ package io.netty.handler.codec.http; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.util.IllegalReferenceCountException; import org.junit.Test; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.Charset; +import java.util.concurrent.ExecutionException; -import static org.junit.Assert.*; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; /** */ @@ -122,4 +129,29 @@ public class HttpRequestEncoderTest { buffer.release(); } } + + @Test + public void testEmptyReleasedBufferShouldNotWriteEmptyBufferToChannel() throws Exception { + HttpRequestEncoder encoder = new HttpRequestEncoder(); + EmbeddedChannel channel = new EmbeddedChannel(encoder); + ByteBuf buf = Unpooled.buffer(); + buf.release(); + try { + channel.writeAndFlush(buf).get(); + fail(); + } catch (ExecutionException e) { + assertThat(e.getCause().getCause(), is(instanceOf(IllegalReferenceCountException.class))); + } + channel.finishAndReleaseAll(); + } + + @Test + public void testEmptydBufferShouldPassThrough() throws Exception { + HttpRequestEncoder encoder = new HttpRequestEncoder(); + EmbeddedChannel channel = new EmbeddedChannel(encoder); + ByteBuf buffer = Unpooled.buffer(); + channel.writeAndFlush(buffer).get(); + channel.finishAndReleaseAll(); + assertEquals(0, buffer.refCnt()); + } } diff --git a/codec/src/main/java/io/netty/handler/codec/MessageAggregator.java b/codec/src/main/java/io/netty/handler/codec/MessageAggregator.java index 2bede688bd..2cdb880c99 100644 --- a/codec/src/main/java/io/netty/handler/codec/MessageAggregator.java +++ b/codec/src/main/java/io/netty/handler/codec/MessageAggregator.java @@ -241,7 +241,7 @@ public abstract class MessageAggregator