1

我在玩 Jetty ( 9.2.3v20140905ServerEndpointConfig ) 时连接了一个 Web 套接字端点,当我遇到 Jetty 的代码以查看它是如何使用的时,我尝试使用我自己的端点。我注意到它在JsrCreator创建 Web 套接字对象时使用:

Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp){
 ...
 // modify handshake
 configurator.modifyHandshake(config,hsreq,hsresp);
 ...
}

我阅读了( javax.websocket-api 1.0 )的javadoc modifyHandshakeServerEndpointConfig其中指出

由容器在形成由格式良好的握手请求产生的握手响应后调用。容器已经检查了这个配置有一个匹配的 URI ,使用checkOrigin 方法确定了源的有效性,并根据这个配置填写了协商的子协议和扩展。自定义配置可能会覆盖此方法,以检查请求参数并修改服务器已制定的握手响应。以及 URI 检查。 如果开发人员不重写此方法,则实现不会对请求和响应进行进一步修改。

以下是 Jetty 的作用:

Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp){
 ...
 // modify handshake
 configurator.modifyHandshake(config,hsreq,hsresp);

 // check origin
 if (!configurator.checkOrigin(req.getOrigin())){...}
 ...
 resp.setAcceptedSubProtocol(subprotocol);
 ...
 resp.setExtensions(configs);
}

如您所见,在调用配置器之后检查原点。在调用配置器之后修改响应。调用 WebSocketCreatoracceptWebSocket的方法:WebSocketServerFactory

Object websocketPojo = creator.createWebSocket(sockreq, sockresp);

之后调用:

private boolean upgrade(HttpConnection http, ServletUpgradeRequest request, ServletUpgradeResponse response, EventDriver driver)

它还通过以下方式修改响应HandshakeRFC6455

 // build response
 response.setHeader("Upgrade","WebSocket");
 response.addHeader("Connection","Upgrade");
 response.addHeader("Sec-WebSocket-Accept",AcceptHash.hashKey(key));

所以我没有办法只用我的配置器来修改响应,因为 Jetty 无论如何都会改变它。

在我看来,Jetty 不符合 JSR 356,即 WebSocket 的 Java API,是吗?

4

1 回答 1

0

啊,JSR-356 规范中许多模棱两可和定义不明确的部分之一。

您可能想阅读针对规范的开放错误

如果完全遵循原始 1.x 规范,那么现实世界中的许多场景示例都是不可能的。

现在,要解决您问题的具体细节:

为什么在 Jetty 实现中 modifyHandshake 之后调用 checkOrigin?

这是因为在某些有效场景(尤其是 CDI 和 Spring)中,最终用户实现所需的信息在调用调用checkOrigin之前是无效的或存在的。modifyHandshake

基本上,端点Configurator被创建,modifyHandshake被调用,此时所有的库集成(CDI、Spring 等)都开始了,也就是端点进入 WebSocket (RFC6455) CONNECTING 状态的时候。(一旦端点的 onOpen 被调用,WebSocket RFC6455 状态就会进入 OPEN 状态)

您可能已经注意到,当涉及 CDI(或 Spring)时,对象的范围和生命周期规范中没有定义。

1.x JSR356 规范实际上与 servlet 容器特定的行为保持距离,这样做是为了使规范尽可能通用,并且也具有非 servlet websocket 服务器容器的能力。不幸的是,这也意味着 servlet 容器中有许多不符合 1.x JSR356 规范的用例。

一旦更新 JSR356 规范以正确定义 WebSocket 上的 CDI 范围,就可以修复这个checkOriginafter的怪癖。modifyHandshake

为什么在 modifyHandshake 之后实现修改响应?

实现必须修改响应,否则响应对 HTTP/1.1 升级无效,实现需要配合端点及其配置、子协议和扩展使这成为现实。(请注意 JSR356 规范对扩展的要求?)

这也是承诺在下一个 JSR356 修订版中更正的领域。

WebSocket over HTTP/2 规范的当前工作使这更加有趣,因为它(当前)没有使用 HTTP/1.1 升级语义。它只是通过握手而存在(没有升级,没有起源等)。

于 2015-05-18T12:53:22.673 回答