Fix handling of FullHttpResponse when respond to HEAD in HttpServerCodec

Motivation:

cb139043f3 introduced special handling of response to HEAD requests. Due a bug we failed to handle FullHttpResponse correctly.

Modifications:

Correctly handle FullHttpResponse for HEAD requests.

Result:

Works as expected.
This commit is contained in:
Norman Maurer 2016-12-21 14:35:53 +01:00
parent 074075de7e
commit 0eeeb76439
2 changed files with 55 additions and 29 deletions

View File

@ -97,12 +97,6 @@ public abstract class HttpObjectEncoder<H extends HttpMessage> extends MessageTo
switch (state) { switch (state) {
case ST_INIT: case ST_INIT:
throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg)); 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: case ST_CONTENT_NON_CHUNK:
final long contentLength = contentLength(msg); final long contentLength = contentLength(msg);
if (contentLength > 0) { if (contentLength > 0) {
@ -116,33 +110,43 @@ public abstract class HttpObjectEncoder<H extends HttpMessage> extends MessageTo
} }
out.add(encodeAndRetain(msg)); out.add(encodeAndRetain(msg));
} }
} else {
if (buf != null) { if (msg instanceof LastHttpContent) {
out.add(buf); state = ST_INIT;
} else {
// Need to produce some output otherwise an
// IllegalStateException will be thrown
out.add(EMPTY_BUFFER);
} }
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) { break;
state = ST_INIT;
}
return;
case ST_CONTENT_CHUNK: case ST_CONTENT_CHUNK:
if (buf != null) { if (buf != null) {
// We allocated a buffer so add it now.
out.add(buf); out.add(buf);
} }
encodeChunkedContent(ctx, msg, contentLength(msg), out); encodeChunkedContent(ctx, msg, contentLength(msg), out);
return;
break;
default: default:
throw new Error(); throw new Error();
} }
} else {
if (buf != null) { if (msg instanceof LastHttpContent) {
out.add(buf); state = ST_INIT;
} }
} else if (buf != null) {
out.add(buf);
} }
} }
@ -184,14 +188,10 @@ public abstract class HttpObjectEncoder<H extends HttpMessage> extends MessageTo
buf.writeBytes(CRLF); buf.writeBytes(CRLF);
out.add(buf); out.add(buf);
} }
} else if (contentLength == 0) {
state = ST_INIT; // Need to produce some output otherwise an
} else { // IllegalstateException will be thrown
if (contentLength == 0) { out.add(EMPTY_BUFFER);
// Need to produce some output otherwise an
// IllegalstateException will be thrown
out.add(EMPTY_BUFFER);
}
} }
} }

View File

@ -145,6 +145,32 @@ public class HttpServerCodecTest {
assertFalse(ch.finishAndReleaseAll()); 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) { private static ByteBuf prepareDataChunk(int size) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {