diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientCodec.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientCodec.java index 9a66fbf8339..40c59fd3387 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientCodec.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientCodec.java @@ -191,7 +191,8 @@ protected void encode( ChannelHandlerContext ctx, Object msg, List out) throws Exception { if (upgraded) { - out.add(ReferenceCountUtil.retain(msg)); + // HttpObjectEncoder overrides .write and does not release msg, so we don't need to retain it here + out.add(msg); return; } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpClientCodecTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpClientCodecTest.java index a320832b43d..5663a6b191e 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpClientCodecTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpClientCodecTest.java @@ -36,6 +36,7 @@ import io.netty.util.CharsetUtil; import io.netty.util.NetUtil; import org.hamcrest.CoreMatchers; +import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import java.net.InetSocketAddress; @@ -423,4 +424,19 @@ public void testMultipleResponses() { assertTrue(ch.finishAndReleaseAll()); } + @Test + public void testWriteThroughAfterUpgrade() { + HttpClientCodec codec = new HttpClientCodec(); + EmbeddedChannel ch = new EmbeddedChannel(codec); + codec.prepareUpgradeFrom(null); + + ByteBuf buffer = ch.alloc().buffer(); + assertThat(buffer.refCnt(), is(1)); + assertTrue(ch.writeOutbound(buffer)); + // buffer should pass through unchanged + assertThat(ch.readOutbound(), sameInstance(buffer)); + assertThat(buffer.refCnt(), is(1)); + + buffer.release(); + } }