【问题标题】:Jetty upgrade (9.2.24 -> 9.4.10) fails with websocket (UpgradeException)Jetty 升级 (9.2.24 -> 9.4.10) 失败并出现 websocket (UpgradeException)
【发布时间】:2018-11-29 06:48:26
【问题描述】:

我正在将我们的 jetty 从 9.2.24 升级到 9.4.10,以开发一个可以广泛使用 websockets 的应用。

我有一个现有的测试(junit),它设置嵌入式码头,向它注册休息资源和 websocket servlet,然后测试它们是否可以访问。

当码头的版本为 9.2.24 时,测试非常好使用完全相同的代码迁移到版本 9.4.10 的尝试失败并显示

java.io.IOException: Connect failure
    at org.eclipse.jetty.websocket.jsr356.ClientContainer.connect(ClientContainer.java:232)
    at org.eclipse.jetty.websocket.jsr356.ClientContainer.connectToServer(ClientContainer.java:255)   
...
Caused by: org.eclipse.jetty.websocket.api.UpgradeException: 400 Bad Request
    at org.eclipse.jetty.websocket.client.WebSocketUpgradeRequest.onComplete(WebSocketUpgradeRequest.java:522)
    at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:193)

服务器端的 websocket 定义基于 JSR356 规范(即扩展 EndPoint)。用于访问 websocket 的 websocket 客户端也基于 javax.websocket(即 ContainerProvider.getWebSocketContainer().connectToServer(Endpoint instance...) - 其中 websocket 容器实际上是一个码头...

服务器设置完美。问题仅在尝试访问 websocket 时出现。我已经调试过了,没有发现客户端发起和发送 websocket 请求的方式有什么不同。特别是请求的“升级”标头按预期设置为“websocket”。

所以我只能假设问题出在嵌入式码头中注册 websocket 资源的方式上。我已经调试了 working 流程(使用 9.2.24)并找到了在码头(AbstractConnection 的选择器线程之一)中接受连接的最早位置。但由于某种原因,在使用 9.4.10 时,我没有达到 websocket 的程度

我已经阅读了一些资源和 SO 问题(例如 this question),但找不到任何可以帮助我解决这个问题的东西。 我陷入了死胡同。

这里是服务器注册相关代码中的关键元素(我还有另一个rest资源以及websocket):

// web socket
ServletContextHandler wsContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
wsContext.setContextPath("/ws_api");
ServerContainer container = WebSocketServerContainerInitializer.configureContext(servletContextHandler);
container.addEndpoint(new BasicServerEndpointConfig(container.getClient(), endpointClassObject, path)

// rest handler
ServletContextHandler restContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
restContext.setContextPath("/rest_api");
...
ServletHolder sh = new ServletHolder(...);
restContext.addServlet(sh, "/*");

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{wsContext, restContext, new DefaultHandler()});
server.setHandler(handlers);

帮助...

更新(根据 Joakim Erdfelt 请求的附加信息):

我在 HTTPConnection 类中,在 BP 中的 onComplete() 方法中,从 _channel._fields 对象中获取请求标头 I得到:

响应对象的状态是 200(而不是预期的 101):

我的端点对象是大型继承链的一部分。它充满了样板业务逻辑代码,我需要在上传之前将其删除,但在根目录中是 javax.websocket.Endpont 类,我们只实现了 onOpen(Session session, EndpointConfig config) 方法。调试时我没有使用该方法,似乎很久以前就失败了......

【问题讨论】:

  • 您需要捕获请求/响应标头才能知道发生了什么。
  • 也许同时显示您的端点和客户端的代码。
  • 用附加信息更新了问题。

标签: websocket embedded-jetty jetty-9


【解决方案1】:

您的请求标头如下所示...

Accept: application/json, application/*+json
Accept-Encoding: gzip
Cache-Control: no-cache
Connection: keep-alive
Content-Type: application/json
Host: 127.0.0.1:8080
Pragma: no-cache
Sec-WebSocket-Key: sMQPm6Cf00itLII3QBb4w==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Java/1.8.0_144

这是一个无效的 WebSocket 升级请求。 最明显的遗漏是

Connection: upgrade

但还有其他字段是兼容的 WebSocket 客户端永远不会设置的。

Content-Type: application/json
Accept: application/json, application/*+json
Accept-Encoding: gzip

【讨论】:

  • 关于连接头,您可能是对的。 (我什至有一个基本的预感,我们在哪里覆盖它)。我错过了。我现在不在工作,我会第一时间检查它,并会相应地更新。您是否认为您提到的其他标头的存在也会破坏代码,或者它在上下文中根本没有意义? (但不应该失败)如果这确实是问题所在 - 这听起来像是在 9.2.24 上运行良好并且在 9.4.10 上会失败吗? (因为它是我在两个版本中使用的完全相同的客户端代码,仅在 9.4.10 上失败)
  • 缺少 Connection: upgrade 导致 Jetty 7.0.x 到 9.4.x 中的 WebSocket 升级失败
  • 确实按预期工作。我看到由于某种原因,当我使用 9.2.x 运行时,我的测试没有覆盖连接头 - 所以问题仍然存在于我的代码中。 Jetty 按预期工作 :) 感谢您提供宝贵的信息。
猜你喜欢
  • 2017-01-19
  • 1970-01-01
  • 1970-01-01
  • 2018-11-26
  • 1970-01-01
  • 2016-03-04
  • 2018-10-30
  • 2021-07-17
  • 2012-12-24
相关资源
最近更新 更多