将Netty用作基本的透明HTTP代理

问题描述 投票:0回答:1

我需要实现充当透明HTTP代理的服务,它需要执行以下操作:

  1. 接收一个HTTP请求(TLS将已经终止,所以我们在这里只说普通的HTTP)
  2. 向请求添加标题
  3. 以非阻塞方式将修改后的请求转发到其预期的目的地
  4. 隐藏/保留请求以备后用
  5. 当响应返回时,将其返回给呼叫者。
  6. 打包响应和请求(存储在#4中,并以非阻塞方式将它们发送到另一个系统。

阅读了Netty文档后,我设法将一些非常原始的东西放在一起,它接受来自客户端的HTTP请求并返回HTTP响应,这在单个服务器管道中利用了以下Netty组件:

  • HttpServerCodec
  • HttpObjectAggregator
  • 我编写的处理程序,扩展了ChannelInboundHandlerAdapter,看起来像这样:

    void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
        try {
            FullHttpRequest httpRequest = (FullHttpRequest) msg
            ensureAuditingHeaderIsPresent(httpRequest)
            ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK))
            println("Response written...")
        }
        finally {
            ReferenceCountUtil.release(msg)
        }
    }```
    

这一切都按照我的预期工作,导致200响应返回给客户端(尽管是空的)。但是,我正在努力了解现在可以采用哪种方法来实现HTTP请求的转发以及将响应返回给客户端。

我最初的想法是使用异步HTTP客户端库,但是我感觉到我缺少Netty内置的某些东西,可以让我在管道中执行此操作?也许某种出站ChannelOutboundHandlerAdapter

您可以说出我目前对Netty内部的了解是非常基本的,非常感谢任何提示!

最终问题:2015年的《行动网》仍然值得一读吗?如果要完全过时,我不愿意购买,但是它仍然有意义,那么也许值得一读?

非常感谢,

Edd

netty
1个回答
0
投票
您将需要两个管道-一个用于服务器端(又称入站通道),另一个用于客户端(又称出站通道),通向目标服务器。收到来自传入通道的处理程序的请求后,您将需要启动与目标服务器的新连接,并传递a)HTTP请求(根据需要进行修改)和b)对传入通道上下文的引用。从目标服务器,传出通道处理程序收到响应后,您可以简单地将响应(根据需要进行修改)写回到传入通道。无需外部库。

一个(经过简化的)伪代码示例将您指向正确的方向:

您的服务器端处理程序将类似于:

void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { try { FullHttpRequest httpRequest = (FullHttpRequest) msg; ensureAuditingHeaderIsPresent(httpRequest); Bootstrap b = new Bootstrap(); b.group(eventLoopGroup) // use the same eventLoopGroup as the server's .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new HttpClientCodec()) .addLast(new HttpObjectAggregator()) .addLast(new MyProxyOutgoingChannelHandler(httpRequest.copy(), ctx)); } }); String targetHost = getTargetHostFromRequest(httpRequest); int targetPort = getTargetPortFromRequest(httpRequest); b.connect(targetHost, targetPort); } finally { ReferenceCountUtil.release(msg); } }

您的传出频道处理程序将如下所示:

class MyProxyOutgoingChannelHandler extends SimpleChannelInboundHandler { private final ChannelHandlerContext incomingChannelCtx; private final HttpRequest httpRequest; void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { FullHttpResponse response = (FullHttpResponse) msg; incomingChannelCtx.writeAndFlush(response); } @Override void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.write(httpRequest); }

希望有所帮助。
© www.soinside.com 2019 - 2024. All rights reserved.