[#494] Automatically adding chunked encoding header breaks streaming
Forwardport @jamestyrrell's pull request
This commit is contained in:
parent
5787e2eac9
commit
0baf359202
@ -151,6 +151,17 @@ final class HttpCodecUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void removeTransferEncodingChunked(HttpMessage m) {
|
||||
List<String> values = m.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
|
||||
values.remove(HttpHeaders.Values.CHUNKED);
|
||||
m.setHeader(HttpHeaders.Names.TRANSFER_ENCODING, values);
|
||||
}
|
||||
|
||||
static boolean isContentLengthSet(HttpMessage m) {
|
||||
List<String> contentLength = m.getHeaders(HttpHeaders.Names.CONTENT_LENGTH);
|
||||
return !contentLength.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* A constructor to ensure that instances of this class are never made
|
||||
*/
|
||||
|
@ -47,7 +47,7 @@ public abstract class HttpMessageEncoder extends MessageToByteEncoder<Object> {
|
||||
private static final ByteBuf LAST_CHUNK =
|
||||
copiedBuffer("0\r\n\r\n", CharsetUtil.US_ASCII);
|
||||
|
||||
private volatile boolean chunked;
|
||||
private boolean transferEncodingChunked;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
@ -64,17 +64,25 @@ public abstract class HttpMessageEncoder extends MessageToByteEncoder<Object> {
|
||||
public void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
|
||||
if (msg instanceof HttpMessage) {
|
||||
HttpMessage m = (HttpMessage) msg;
|
||||
boolean chunked;
|
||||
boolean contentMustBeEmmpty;
|
||||
if (m.isChunked()) {
|
||||
// check if the Transfer-Encoding is set to chunked already.
|
||||
// if not add the header to the message
|
||||
if (!HttpCodecUtil.isTransferEncodingChunked(m)) {
|
||||
m.addHeader(Names.TRANSFER_ENCODING, Values.CHUNKED);
|
||||
// if Content-Length is set then the message can't be HTTP chunked
|
||||
if (HttpCodecUtil.isContentLengthSet(m)) {
|
||||
contentMustBeEmmpty = false;
|
||||
transferEncodingChunked = false;
|
||||
} else {
|
||||
// check if the Transfer-Encoding is set to chunked already.
|
||||
// if not add the header to the message
|
||||
if (!HttpCodecUtil.isTransferEncodingChunked(m)) {
|
||||
m.addHeader(Names.TRANSFER_ENCODING, Values.CHUNKED);
|
||||
}
|
||||
contentMustBeEmmpty = true;
|
||||
transferEncodingChunked = true;
|
||||
}
|
||||
chunked = this.chunked = true;
|
||||
} else {
|
||||
chunked = this.chunked = HttpCodecUtil.isTransferEncodingChunked(m);
|
||||
transferEncodingChunked = contentMustBeEmmpty = HttpCodecUtil.isTransferEncodingChunked(m);
|
||||
}
|
||||
|
||||
out.markWriterIndex();
|
||||
encodeInitialLine(out, m);
|
||||
encodeHeaders(out, m);
|
||||
@ -83,20 +91,19 @@ public abstract class HttpMessageEncoder extends MessageToByteEncoder<Object> {
|
||||
|
||||
ByteBuf content = m.getContent();
|
||||
if (content.readable()) {
|
||||
if (chunked) {
|
||||
if (contentMustBeEmmpty) {
|
||||
out.resetWriterIndex();
|
||||
throw new IllegalArgumentException(
|
||||
"HttpMessage.content must be empty " +
|
||||
"if Transfer-Encoding is chunked.");
|
||||
"HttpMessage.content must be empty if Transfer-Encoding is chunked.");
|
||||
} else {
|
||||
out.writeBytes(content, content.readerIndex(), content.readableBytes());
|
||||
}
|
||||
}
|
||||
} else if (msg instanceof HttpChunk) {
|
||||
HttpChunk chunk = (HttpChunk) msg;
|
||||
if (chunked) {
|
||||
if (transferEncodingChunked) {
|
||||
if (chunk.isLast()) {
|
||||
chunked = false;
|
||||
transferEncodingChunked = false;
|
||||
if (chunk instanceof HttpChunkTrailer) {
|
||||
out.writeByte((byte) '0');
|
||||
out.writeByte(CR);
|
||||
|
Loading…
Reference in New Issue
Block a user