如何为http代理

时间:2015-07-27 13:42:20

标签: java http netty http-proxy

我使用Netty写了一个小的http代理,它已经运行了一段时间了。今天我开始在来自单个客户端的日志文件中得到奇怪的异常:

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]

查找源代码时,在发送100 Continue状态以响应POST请求(HttpObjectAggregator行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());
            }
        }
    });
}

实际上导致问题的客户端似乎是唯一一个与请求一起发送Expect: 100-continue标头的客户端。这让我觉得我的处理程序管道设置错误了:

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(...));

HttpObjectAggregator的API文档说明了

  

请注意,您需要在ChannelPipeline中的HttpObjectAggregator之前使用HttpResponseEncoder或HttpRequestEncoder。

所以我认为HttpRequestDecoderHttpResponseEncoder应该在管道中的HttpObjectAggregator之前。这可能是我的问题吗?

1 个答案:

答案 0 :(得分:2)

您是否尝试更改订单(聚合器是MyHandler之前的最后一个订单)?