[#1648] Make sure trailing headers are not dropped during content encoding/decoding
This commit is contained in:
parent
d5bf1a1187
commit
6873111d72
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package io.netty.handler.codec.http;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.handler.codec.DecoderResult;
|
||||||
|
|
||||||
|
|
||||||
|
final class ComposedLastHttpContent implements LastHttpContent {
|
||||||
|
private final HttpHeaders trailingHeaders;
|
||||||
|
private DecoderResult result;
|
||||||
|
|
||||||
|
ComposedLastHttpContent(HttpHeaders trailingHeaders) {
|
||||||
|
this.trailingHeaders = trailingHeaders;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public HttpHeaders trailingHeaders() {
|
||||||
|
return trailingHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LastHttpContent copy() {
|
||||||
|
LastHttpContent content = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER);
|
||||||
|
content.trailingHeaders().set(trailingHeaders());
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LastHttpContent retain(int increment) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LastHttpContent retain() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpContent duplicate() {
|
||||||
|
return copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf content() {
|
||||||
|
return Unpooled.EMPTY_BUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DecoderResult getDecoderResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDecoderResult(DecoderResult result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int refCnt() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean release() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean release(int decrement) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -153,9 +153,15 @@ public abstract class HttpContentDecoder extends MessageToMessageDecoder<HttpObj
|
|||||||
if (c instanceof LastHttpContent) {
|
if (c instanceof LastHttpContent) {
|
||||||
finishDecode(out);
|
finishDecode(out);
|
||||||
|
|
||||||
|
LastHttpContent last = (LastHttpContent) c;
|
||||||
// Generate an additional chunk if the decoder produced
|
// Generate an additional chunk if the decoder produced
|
||||||
// the last product on closure,
|
// the last product on closure,
|
||||||
|
HttpHeaders headers = last.trailingHeaders();
|
||||||
|
if (headers.isEmpty()) {
|
||||||
out.add(LastHttpContent.EMPTY_LAST_CONTENT);
|
out.add(LastHttpContent.EMPTY_LAST_CONTENT);
|
||||||
|
} else {
|
||||||
|
out.add(new ComposedLastHttpContent(headers));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,8 +160,7 @@ public abstract class HttpContentEncoder extends MessageToMessageCodec<HttpReque
|
|||||||
}
|
}
|
||||||
case AWAIT_CONTENT: {
|
case AWAIT_CONTENT: {
|
||||||
ensureContent(msg);
|
ensureContent(msg);
|
||||||
encodeContent((HttpContent) msg, out);
|
if (encodeContent((HttpContent) msg, out)) {
|
||||||
if (msg instanceof LastHttpContent) {
|
|
||||||
state = State.AWAIT_HEADERS;
|
state = State.AWAIT_HEADERS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -194,18 +193,26 @@ public abstract class HttpContentEncoder extends MessageToMessageCodec<HttpReque
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeContent(HttpContent c, List<Object> out) {
|
private boolean encodeContent(HttpContent c, List<Object> out) {
|
||||||
ByteBuf content = c.content();
|
ByteBuf content = c.content();
|
||||||
|
|
||||||
encode(content, out);
|
encode(content, out);
|
||||||
|
|
||||||
if (c instanceof LastHttpContent) {
|
if (c instanceof LastHttpContent) {
|
||||||
finishEncode(out);
|
finishEncode(out);
|
||||||
|
LastHttpContent last = (LastHttpContent) c;
|
||||||
|
|
||||||
// Generate an additional chunk if the decoder produced
|
// Generate an additional chunk if the decoder produced
|
||||||
// the last product on closure,
|
// the last product on closure,
|
||||||
|
HttpHeaders headers = last.trailingHeaders();
|
||||||
|
if (headers.isEmpty()) {
|
||||||
out.add(LastHttpContent.EMPTY_LAST_CONTENT);
|
out.add(LastHttpContent.EMPTY_LAST_CONTENT);
|
||||||
|
} else {
|
||||||
|
out.add(new ComposedLastHttpContent(headers));
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user