Correctly handle 205 Reset Content response with transfer-encoding

Motivation:

According to RFC 7231 the server may choose to:
```
indicate a zero-length payload for the response by including a
Transfer-Encoding header field with a value of chunked and a message
body consisting of a single chunk of zero-length
```
https://tools.ietf.org/html/rfc7231#page-53

In such cases the exception below appears during decoding phase:
```
java.lang.IllegalArgumentException: invalid version format: 0
	at io.netty.handler.codec.http.HttpVersion.<init>(HttpVersion.java:121)
	at io.netty.handler.codec.http.HttpVersion.valueOf(HttpVersion.java:76)
	at io.netty.handler.codec.http.HttpResponseDecoder.createMessage(HttpResponseDecoder.java:118)
	at io.netty.handler.codec.http.HttpObjectDecoder.decode(HttpObjectDecoder.java:219)
```

Modifications:

HttpObjectDecoder.isContentAlwaysEmpty specifies content NOT empty
when 205 Reset Content response

Result:

There is no `IllegalArgumentException: invalid version format: 0`
when handling 205 Reset Content response with transfer-encoding
This commit is contained in:
Violeta Georgieva 2017-11-10 10:33:29 +02:00 committed by Norman Maurer
parent 25d146038c
commit 72a216625f
2 changed files with 23 additions and 1 deletions

View File

@ -477,7 +477,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
}
switch (code) {
case 204: case 205: case 304:
case 204: case 304:
return true;
}
}

View File

@ -368,6 +368,28 @@ public class HttpResponseDecoderTest {
assertThat(ch.readInbound(), is(nullValue()));
}
@Test
public void testResetContentResponseWithTransferEncoding() {
EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder());
assertTrue(ch.writeInbound(Unpooled.copiedBuffer(
"HTTP/1.1 205 Reset Content\r\n" +
"Transfer-Encoding: chunked\r\n" +
"\r\n" +
"0\r\n" +
"\r\n",
CharsetUtil.US_ASCII)));
HttpResponse res = ch.readInbound();
assertThat(res.protocolVersion(), sameInstance(HttpVersion.HTTP_1_1));
assertThat(res.status(), is(HttpResponseStatus.RESET_CONTENT));
LastHttpContent lastContent = ch.readInbound();
assertThat(lastContent.content().isReadable(), is(false));
lastContent.release();
assertThat(ch.finish(), is(false));
}
@Test
public void testLastResponseWithTrailingHeader() {
EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder());