Ensure valid message sequence if channel is closed before receive headers.
Motivation: When the channel is closed while we still decode the headers we currently not preserve correct message sequence. In this case we should generate an invalid message with a current cause. Modifications: Create an invalid message with a PrematureChannelClosureException as cause when the channel is closed while we decode the headers. Result: Correct message sequence preserved and correct DecoderResult if the channel is closed while decode headers.
This commit is contained in:
parent
c5d70ec7dc
commit
12911a0efe
@ -22,6 +22,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.DecoderResult;
|
||||
import io.netty.handler.codec.PrematureChannelClosureException;
|
||||
import io.netty.handler.codec.TooLongFrameException;
|
||||
import io.netty.util.internal.AppendableCharSequence;
|
||||
|
||||
@ -413,9 +414,19 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
if (currentState == State.READ_VARIABLE_LENGTH_CONTENT && !in.isReadable() && !chunked) {
|
||||
// End of connection.
|
||||
out.add(LastHttpContent.EMPTY_LAST_CONTENT);
|
||||
reset();
|
||||
resetNow();
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentState == State.READ_HEADER) {
|
||||
// If we are still in the state of reading headers we need to create a new invalid message that
|
||||
// signals that the connection was closed before we received the headers.
|
||||
out.add(invalidMessage(Unpooled.EMPTY_BUFFER,
|
||||
new PrematureChannelClosureException("Connection closed before received headers")));
|
||||
resetNow();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the closure of the connection signifies the end of the content.
|
||||
boolean prematureClosure;
|
||||
if (isDecodingRequest() || chunked) {
|
||||
@ -427,11 +438,11 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
// connection, so it is perfectly fine.
|
||||
prematureClosure = contentLength() > 0;
|
||||
}
|
||||
resetNow();
|
||||
|
||||
if (!prematureClosure) {
|
||||
out.add(LastHttpContent.EMPTY_LAST_CONTENT);
|
||||
}
|
||||
resetNow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ package io.netty.handler.codec.http;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.embedded.EmbeddedChannel;
|
||||
import io.netty.handler.codec.PrematureChannelClosureException;
|
||||
import io.netty.handler.codec.TooLongFrameException;
|
||||
import io.netty.handler.codec.http.HttpHeaders.Names;
|
||||
import io.netty.util.CharsetUtil;
|
||||
@ -611,4 +612,17 @@ public class HttpResponseDecoderTest {
|
||||
// .. even after the connection is closed.
|
||||
assertThat(channel.finish(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionClosedBeforeHeadersReceived() {
|
||||
EmbeddedChannel channel = new EmbeddedChannel(new HttpResponseDecoder());
|
||||
String responseInitialLine =
|
||||
"HTTP/1.1 200 OK\r\n";
|
||||
assertFalse(channel.writeInbound(Unpooled.copiedBuffer(responseInitialLine, CharsetUtil.US_ASCII)));
|
||||
assertTrue(channel.finish());
|
||||
HttpMessage message = (HttpMessage) channel.readInbound();
|
||||
assertTrue(message.getDecoderResult().isFailure());
|
||||
assertThat(message.getDecoderResult().cause(), instanceOf(PrematureChannelClosureException.class));
|
||||
assertNull(channel.readInbound());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user