Make it configurable if the HttpClientCodec should throw an exception on close when the response and request count does not match. Default is false. See #266

This commit is contained in:
Norman Maurer 2012-04-17 20:54:58 +02:00
parent d808cd0475
commit 54559a9595
2 changed files with 32 additions and 15 deletions

View File

@ -57,14 +57,16 @@ public class HttpClientCodec implements ChannelUpstreamHandler,
private final HttpRequestEncoder encoder = new Encoder(); private final HttpRequestEncoder encoder = new Encoder();
private final HttpResponseDecoder decoder; private final HttpResponseDecoder decoder;
private final AtomicLong requestResponseCounter = new AtomicLong(0); private final AtomicLong requestResponseCounter = new AtomicLong(0);
private final boolean failOnMissingResponse;
/** /**
* Creates a new instance with the default decoder options * Creates a new instance with the default decoder options
* ({@code maxInitialLineLength (4096}}, {@code maxHeaderSize (8192)}, and * ({@code maxInitialLineLength (4096}}, {@code maxHeaderSize (8192)}, and
* {@code maxChunkSize (8192)}). * {@code maxChunkSize (8192)}).
*
*/ */
public HttpClientCodec() { public HttpClientCodec() {
this(4096, 8192, 8192); this(4096, 8192, 8192, false);
} }
/** /**
@ -72,7 +74,16 @@ public class HttpClientCodec implements ChannelUpstreamHandler,
*/ */
public HttpClientCodec( public HttpClientCodec(
int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) { int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) {
this(maxInitialLineLength, maxHeaderSize, maxChunkSize, false);
}
/**
* Creates a new instance with the specified decoder options.
*/
public HttpClientCodec(
int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean failOnMissingResponse) {
decoder = new Decoder(maxInitialLineLength, maxHeaderSize, maxChunkSize); decoder = new Decoder(maxInitialLineLength, maxHeaderSize, maxChunkSize);
this.failOnMissingResponse = failOnMissingResponse;
} }
@Override @Override
@ -101,6 +112,7 @@ public class HttpClientCodec implements ChannelUpstreamHandler,
Object obj = super.encode(ctx, channel, msg); Object obj = super.encode(ctx, channel, msg);
if (failOnMissingResponse) {
// check if the request is chunked if so do not increment // check if the request is chunked if so do not increment
if (msg instanceof HttpRequest && !((HttpRequest) msg).isChunked()) { if (msg instanceof HttpRequest && !((HttpRequest) msg).isChunked()) {
requestResponseCounter.incrementAndGet(); requestResponseCounter.incrementAndGet();
@ -108,6 +120,7 @@ public class HttpClientCodec implements ChannelUpstreamHandler,
// increment as its the last chunk // increment as its the last chunk
requestResponseCounter.incrementAndGet(); requestResponseCounter.incrementAndGet();
} }
}
return obj; return obj;
@ -127,7 +140,9 @@ public class HttpClientCodec implements ChannelUpstreamHandler,
return buffer.readBytes(actualReadableBytes()); return buffer.readBytes(actualReadableBytes());
} else { } else {
Object msg = super.decode(ctx, channel, buffer, state); Object msg = super.decode(ctx, channel, buffer, state);
if (failOnMissingResponse) {
decrement(msg); decrement(msg);
}
return msg; return msg;
} }
} }
@ -204,11 +219,13 @@ public class HttpClientCodec implements ChannelUpstreamHandler,
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
super.channelClosed(ctx, e); super.channelClosed(ctx, e);
if (failOnMissingResponse) {
long missingResponses = requestResponseCounter.get(); long missingResponses = requestResponseCounter.get();
if (missingResponses > 0) { if (missingResponses > 0) {
throw new PrematureChannelClosureException("Channel closed but still missing " + missingResponses + " response(s)"); throw new PrematureChannelClosureException("Channel closed but still missing " + missingResponses + " response(s)");
} }
} }
}
} }

View File

@ -38,7 +38,7 @@ public class HttpClientCodecTest {
@Test @Test
public void testFailsNotOnRequestResponse() { public void testFailsNotOnRequestResponse() {
HttpClientCodec codec = new HttpClientCodec(); HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true);
DecoderEmbedder<ChannelBuffer> decoder = new DecoderEmbedder<ChannelBuffer>(codec); DecoderEmbedder<ChannelBuffer> decoder = new DecoderEmbedder<ChannelBuffer>(codec);
EncoderEmbedder<ChannelBuffer> encoder = new EncoderEmbedder<ChannelBuffer>(codec); EncoderEmbedder<ChannelBuffer> encoder = new EncoderEmbedder<ChannelBuffer>(codec);
@ -52,7 +52,7 @@ public class HttpClientCodecTest {
@Test @Test
public void testFailsNotOnRequestResponseChunked() { public void testFailsNotOnRequestResponseChunked() {
HttpClientCodec codec = new HttpClientCodec(); HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true);
DecoderEmbedder<ChannelBuffer> decoder = new DecoderEmbedder<ChannelBuffer>(codec); DecoderEmbedder<ChannelBuffer> decoder = new DecoderEmbedder<ChannelBuffer>(codec);
EncoderEmbedder<ChannelBuffer> encoder = new EncoderEmbedder<ChannelBuffer>(codec); EncoderEmbedder<ChannelBuffer> encoder = new EncoderEmbedder<ChannelBuffer>(codec);
@ -66,7 +66,7 @@ public class HttpClientCodecTest {
@Test @Test
public void testFailsOnMissingResponse() { public void testFailsOnMissingResponse() {
HttpClientCodec codec = new HttpClientCodec(); HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true);
EncoderEmbedder<ChannelBuffer> encoder = new EncoderEmbedder<ChannelBuffer>(codec); EncoderEmbedder<ChannelBuffer> encoder = new EncoderEmbedder<ChannelBuffer>(codec);
encoder.offer(new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/")); encoder.offer(new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/"));
@ -82,7 +82,7 @@ public class HttpClientCodecTest {
@Test @Test
public void testFailsOnIncompleteChunkedResponse() { public void testFailsOnIncompleteChunkedResponse() {
HttpClientCodec codec = new HttpClientCodec(); HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true);
DecoderEmbedder<ChannelBuffer> decoder = new DecoderEmbedder<ChannelBuffer>(codec); DecoderEmbedder<ChannelBuffer> decoder = new DecoderEmbedder<ChannelBuffer>(codec);
EncoderEmbedder<ChannelBuffer> encoder = new EncoderEmbedder<ChannelBuffer>(codec); EncoderEmbedder<ChannelBuffer> encoder = new EncoderEmbedder<ChannelBuffer>(codec);