【发布时间】: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