gpt4 book ai didi

java - 如何解码 http 请求的响应并在 netty 中使用内容?

转载 作者:行者123 更新时间:2023-12-01 23:54:45 26 4
gpt4 key购买 nike

这与 this question 相关,但我正在尝试将问题分解为更小的步骤。

我正在尝试使用netty编写一个简单的http服务器(服务器A),它接收http请求,向另一台服务器(服务器B)发出http请求,然后将响应中的内容复制到对初始请求。我知道有一些如何做到这一点的示例,例如 LittleProxy,但代码相当复杂,而且由于我对 netty 很陌生,所以我试图使我的第一个代码尽可能简单,而无需陷入困境杂草。

目前,我忽略了所有关于并发性的问题,只建立了一个从服务器 A 到服务器 B 的 channel (我知道这会因并发请求而严重中断,但它使我的初始任务更简单)。

我的方法如下:

  1. 设置客户端 Bootstrap 并连接到在本地主机端口 18080 上运行的服务器 B。获取相应的 channel 。

  2. 启动服务器 A 监听端口 2080,并使用管道解码 http 请求,然后写入到服务器 B 的 channel 。

  3. 向生成的 channel future 添加一个监听器,该监听器会将服务器 B 的响应内容复制到对服务器 A 的原始客户端请求的响应。

这是我的代码(非常短),我试图在其中完全按照上面描述的方式进行操作。我的问题是我不知道如何将服务器 B 的响应复制到服务器的响应。当我在服务器 A 发送的响应中写入原始客户端时,我发现执行此操作的一种方法会导致 IllegalArgumentException(我检查了 ChannelBuffer 的内容,并且代理服务器返回了正确的文本)。我在下面粘贴了异常的部分堆栈跟踪。欢迎其他评论,因为除了明显缺乏对服务器 B channel 的锁定之外,我可能还会犯其他错误:

public class NettyExample {

private static Channel channel;
private static Map<Channel, Channel> proxyToClient = new ConcurrentHashMap<Channel, Channel>();

public static void main(String[] args) throws Exception {
ChannelFactory clientFactory =
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
final ClientBootstrap cb = new ClientBootstrap(clientFactory);
cb.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new HttpRequestEncoder(),
new HttpResponseDecoder(),
new ResponseHandler());
}
});
ChannelFuture cf = cb.connect(new InetSocketAddress("localhost", 18080));
channel = cf.awaitUninterruptibly().getChannel();

ChannelFactory factory =
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
ServerBootstrap sb = new ServerBootstrap(factory);

sb.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new HttpRequestDecoder(),
new RequestHandler());
}
});

sb.setOption("child.tcpNoDelay", true);
sb.setOption("child.keepAlive", true);

sb.bind(new InetSocketAddress(2080));
}

private static class ResponseHandler extends SimpleChannelHandler {

@Override
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
final HttpResponse proxyResponse = (HttpResponse) e.getMessage();
Channel clientChannel = proxyToClient.get(e.getChannel());
HttpResponse clientResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
clientResponse.setContent(proxyResponse.getContent());
clientChannel.write(clientResponse).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
Channel ch = future.getChannel();
ch.close();
}
});
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
Channel ch = e.getChannel();
ch.close();
}
}

private static class RequestHandler extends SimpleChannelHandler {

@Override
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
final HttpRequest request = (HttpRequest) e.getMessage();
System.out.println("calling client channel");
proxyToClient.put(channel, e.getChannel());
channel.write(request);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
Channel ch = e.getChannel();
ch.close();
}
}
}

这个中继调用似乎有效,直到调用 clientChannel.write(clientResponse) 为止。在那里,生成以下异常:

java.lang.IllegalArgumentException: unsupported message type: class org.jboss.netty.handler.codec.http.DefaultHttpResponse
at org.jboss.netty.channel.socket.nio.SocketSendBufferPool.acquire(SocketSendBufferPool.java:53)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.write0(AbstractNioWorker.java:468)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromTaskLoop(AbstractNioWorker.java:432)

最佳答案

您需要设置一个客户端管道来等待响应,然后将其写入您的响应。

查看窥探客户端 example ;具体来说,HttpSnoopClientHandler .

关于java - 如何解码 http 请求的响应并在 netty 中使用内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15772620/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com