只是想知道是否有人使用嵌入式Jetty试验过WebSocket代理(透明代理)?
用Jetty 9.1.2.v20140210玩了大约一天半之后,我所知道的是它无法以当前形式代理WebSockets,并且添加这样的支持是非常重要的任务(至少是afaict)
基本上,Jetty ProxyServlet剥离了“Upgrade”和“Connection”头字段,无论它是否来自WebSocket握手请求。将这些字段添加回来很容易,如下所示。但是,当代理服务器返回带有HTTP代码101(切换协议)的响应时,代理服务器上不会进行协议升级。因此,当第一个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());
}
}
}
}
}
}
}
答案 0 :(得分:1)
让我们假设您正在尝试构建的代理方案,我们有客户 A ,服务器 B 和代理 P 。现在让我们来看看连接工作流程: 1. A 与代理 P (A-P)建立的TCP连接 2. A 使用WebSocket握手发送 CONNECT addr(B)请求
这里有第一个问题,WS握手中使用的HTTP RFC标头不是端到端标头,因为对于HTTP,它们仅在传输层(两个跃点之间)有意义。
这是另一个问题,在发送HTTP 101服务器 B 之后,客户端 A 现在只能通过TCP进行通信,但是jetty servlet不支持普通的TCP数据包传播。换句话说,jetty代理servlet会等到客户端 A 开始传输HTTP请求,这在 A 接收HTTP 101后永远不会发生。
您需要使用WS服务器和WS客户端自行实现。