3

I wrote a small http proxy using Netty and it has worked fine for some time now. Today I began getting strange exceptions in the log file coming from a single client:

java.lang.UnsupportedOperationException: unsupported message type: DefaultFullHttpResponse (expected: ByteBuf, FileRegion)
    at io.netty.channel.nio.AbstractNioByteChannel.filterOutboundMessage(AbstractNioByteChannel.java:276) ~[netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:654) ~[netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1054) ~[netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:658) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:716) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:651) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.handler.logging.LoggingHandler.write(LoggingHandler.java:289) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:658) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:716) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:706) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:741) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.handler.codec.http.HttpObjectAggregator.decode(HttpObjectAggregator.java:131) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.handler.codec.http.HttpObjectAggregator.decode(HttpObjectAggregator.java:54) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:163) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.handler.logging.LoggingHandler.channelRead(LoggingHandler.java:283) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:130) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137) [netty-all-4.0.23.Final.jar:4.0.23.Final]
    at java.lang.Thread.run(Thread.java:745) [na:1.7.0_79]

Looking up the source code it seems the problem occurs when sending a 100 Continue status in response to a POST request (HttpObjectAggregator lines 130-139)

if (is100ContinueExpected(m)) {
    ctx.writeAndFlush(CONTINUE).addListener(new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future) 
                throws Exception {
            if (!future.isSuccess()) {
                ctx.fireExceptionCaught(future.cause());
            }
        }
    });
}

and indeed the client causing the issue seems to be the only one sending an Expect: 100-continue header along with the request. This makes me think my handler pipeline could be setup wrong:

p.addLast(new LoggingHandler(LogLevel.DEBUG));
p.addLast(new HttpRequestDecoder());
p.addLast(new HttpObjectAggregator(MAX_CONTENT_LENGTH));
p.addLast(new HttpResponseEncoder());
p.addLast(new MyHandler(...));

The API docs for HttpObjectAggregator state that

Be aware that you need to have the HttpResponseEncoder or HttpRequestEncoder before the HttpObjectAggregator in the ChannelPipeline.

So I'm thinking both the HttpRequestDecoder and HttpResponseEncoder should precede HttpObjectAggregator in the pipeline. Could that be my problem?

1
  • Did you try changing the order (Aggregator being the last one before your MyHandler)? Commented Jul 28, 2015 at 18:02

1 Answer 1

2

Did you try changing the order (Aggregator being the last one before your MyHandler)?

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.