Fix writing of empty LastHttpContent with trailers
Motivation:
4732fabb16
introduced a regression in HttpObjectEncoder which will lead to buffer leak and IllegalStateException when a LastHttpContent with trailers is written.
Modifications:
- Correctly add the buffer to the encoded list.
- Add testcases
Result:
Fixes [#7418]
This commit is contained in:
parent
5ca273814f
commit
8009c4c8a0
@ -206,6 +206,7 @@ public abstract class HttpObjectEncoder<H extends HttpMessage> extends MessageTo
|
||||
buf.writeBytes(CRLF);
|
||||
trailersEncodedSizeAccumulator = TRAILERS_WEIGHT_NEW * padSizeForAccumulation(buf.readableBytes()) +
|
||||
TRAILERS_WEIGHT_HISTORICAL * trailersEncodedSizeAccumulator;
|
||||
out.add(buf);
|
||||
}
|
||||
} else if (contentLength == 0) {
|
||||
// Need to produce some output otherwise an
|
||||
|
@ -135,16 +135,26 @@ public class HttpRequestEncoderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyContentChunked() throws Exception {
|
||||
testEmptyContent(true);
|
||||
public void testEmptyContentsChunked() throws Exception {
|
||||
testEmptyContents(true, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyContentNotChunked() throws Exception {
|
||||
testEmptyContent(false);
|
||||
public void testEmptyContentsChunkedWithTrailers() throws Exception {
|
||||
testEmptyContents(true, true);
|
||||
}
|
||||
|
||||
private void testEmptyContent(boolean chunked) throws Exception {
|
||||
@Test
|
||||
public void testEmptyContentsNotChunked() throws Exception {
|
||||
testEmptyContents(false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyContentNotsChunkedWithTrailers() throws Exception {
|
||||
testEmptyContents(false, true);
|
||||
}
|
||||
|
||||
private void testEmptyContents(boolean chunked, boolean trailers) throws Exception {
|
||||
HttpRequestEncoder encoder = new HttpRequestEncoder();
|
||||
EmbeddedChannel channel = new EmbeddedChannel(encoder);
|
||||
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/");
|
||||
@ -157,7 +167,11 @@ public class HttpRequestEncoderTest {
|
||||
assertTrue(channel.writeOutbound(new DefaultHttpContent(contentBuffer)));
|
||||
|
||||
ByteBuf lastContentBuffer = Unpooled.buffer();
|
||||
assertTrue(channel.writeOutbound(new DefaultHttpContent(lastContentBuffer)));
|
||||
LastHttpContent last = new DefaultLastHttpContent(lastContentBuffer);
|
||||
if (trailers) {
|
||||
last.trailingHeaders().set("X-Netty-Test", "true");
|
||||
}
|
||||
assertTrue(channel.writeOutbound(last));
|
||||
|
||||
// Ensure we only produce ByteBuf instances.
|
||||
ByteBuf head = (ByteBuf) channel.readOutbound();
|
||||
|
@ -286,4 +286,55 @@ public class HttpResponseEncoderTest {
|
||||
buffer = (ByteBuf) channel.readOutbound();
|
||||
buffer.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyContentsChunked() throws Exception {
|
||||
testEmptyContents(true, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyContentsChunkedWithTrailers() throws Exception {
|
||||
testEmptyContents(true, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyContentsNotChunked() throws Exception {
|
||||
testEmptyContents(false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyContentNotsChunkedWithTrailers() throws Exception {
|
||||
testEmptyContents(false, true);
|
||||
}
|
||||
|
||||
private void testEmptyContents(boolean chunked, boolean trailers) throws Exception {
|
||||
HttpResponseEncoder encoder = new HttpResponseEncoder();
|
||||
EmbeddedChannel channel = new EmbeddedChannel(encoder);
|
||||
HttpResponse request = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
|
||||
if (chunked) {
|
||||
HttpHeaders.setTransferEncodingChunked(request);
|
||||
}
|
||||
assertTrue(channel.writeOutbound(request));
|
||||
|
||||
ByteBuf contentBuffer = Unpooled.buffer();
|
||||
assertTrue(channel.writeOutbound(new DefaultHttpContent(contentBuffer)));
|
||||
|
||||
ByteBuf lastContentBuffer = Unpooled.buffer();
|
||||
LastHttpContent last = new DefaultLastHttpContent(lastContentBuffer);
|
||||
if (trailers) {
|
||||
last.trailingHeaders().set("X-Netty-Test", "true");
|
||||
}
|
||||
assertTrue(channel.writeOutbound(last));
|
||||
|
||||
// Ensure we only produce ByteBuf instances.
|
||||
ByteBuf head = (ByteBuf) channel.readOutbound();
|
||||
assertTrue(head.release());
|
||||
|
||||
ByteBuf content = (ByteBuf) channel.readOutbound();
|
||||
content.release();
|
||||
|
||||
ByteBuf lastContent = (ByteBuf) channel.readOutbound();
|
||||
lastContent.release();
|
||||
assertFalse(channel.finish());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user