gpt4 book ai didi

proxy - Jetty WebSocket 代理

转载 作者:行者123 更新时间:2023-12-03 12:00:12 24 4
gpt4 key购买 nike

只是想知道是否有人尝试过使用嵌入式 Jetty 进行 WebSocket 代理(用于透明代理)?
在玩了 Jetty 9.1.2.v20140210 大约一天半之后,我只能说它不能代理当前形式的 WebSockets,并且添加这样的支持是一项不平凡的任务(至少 afact )。
基本上,Jetty ProxyServlet 会去除“升级”和“连接” header 字段,无论它是否来自 WebSocket 握手请求。添加这些字段很容易,如下所示。但是,当代理服务器返回带有 HTTP 代码 101(切换协议(protocol))的响应时,代理服务器上不会进行任何协议(protocol)升级。因此,当第一个 WebSocket 数据包到达时,HttpParser 阻塞并将其视为错误的 HTTP 请求。
如果有人已经有解决方案或熟悉 Jetty 建议尝试什么,那将不胜感激。
下面是我实验中去掉不重要部分的代码:

    public class ProxyServer
{
public static void main(String[] args) throws Exception
{
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8888);
server.addConnector(connector);

// Setup proxy handler to handle CONNECT methods
ConnectHandler proxy = new ConnectHandler();
server.setHandler(proxy);

// Setup proxy servlet
ServletContextHandler context = new ServletContextHandler(proxy, "/", ServletContextHandler.SESSIONS);
ServletHolder proxyServlet = new ServletHolder(MyProxyServlet.class);
context.addServlet(proxyServlet, "/*");

server.start();
}
}

@SuppressWarnings("serial")
public class MyProxyServlet extends ProxyServlet
{
@Override
protected void customizeProxyRequest(Request proxyRequest, HttpServletRequest request)
{
// Pass through the upgrade and connection header fields for websocket handshake request.
String upgradeValue = request.getHeader("Upgrade");
if (upgradeValue != null && upgradeValue.compareToIgnoreCase("websocket") == 0)
{
setHeader(proxyRequest, "Upgrade", upgradeValue);
setHeader(proxyRequest, "Connection", request.getHeader("Connection"));
}
}

@Override
protected void onResponseHeaders(HttpServletRequest request, HttpServletResponse response, Response proxyResponse)
{
super.onResponseHeaders(request, response, proxyResponse);

// Restore the upgrade and connection header fields for websocket handshake request.
HttpFields fields = proxyResponse.getHeaders();
for (HttpField field : fields)
{
if (field.getName().compareToIgnoreCase("Upgrade") == 0)
{
String upgradeValue = field.getValue();
if (upgradeValue != null && upgradeValue.compareToIgnoreCase("websocket") == 0)
{
response.setHeader(field.getName(), upgradeValue);
for (HttpField searchField : fields)
{
if (searchField.getName().compareToIgnoreCase("Connection") == 0) {
response.setHeader(searchField.getName(), searchField.getValue());
}
}
}
}
}
}
}

最佳答案

让我们想象一下您正在尝试构建的代理方案,我们有客户端 一个 , 服务器 和代理电话 .现在让我们来看看连接工作流程:

  • 一个 与代理建立 TCP 连接 电话 (AP)
  • 一个 使用 WebSocket 握手发送 CONNECT addr(B) 请求

  • 第一个问题, HTTP RFC WS 握手中使用的 header 不是端到端 header ,因为对于 HTTP,它们仅在传输层(两跳之间)才有意义。
  • 电话 建立到 的 TCP 连接乙 (PB)
  • 电话 发送 WS 握手 HTTP 请求乙
  • 响应 HTTP->WS 升级(通过发送 101)

  • 这是另一个问题,在发送 HTTP 101 服务器后 和客户 一个 现在将仅通过 TCP 进行通信,但 jetty servlet 不支持纯 TCP 数据包传播。换句话说, jetty 代理 servlet 一直等到客户端 一个 将开始传输 HTTP 请求,这在 之后永远不会发生一个 将收到 HTTP 101。
    您需要自己使用 WS 服务器和 WS 客户端来实现这一点。

    关于proxy - Jetty WebSocket 代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22262468/

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