这是否可以在相同的上下文中服务器websocket处理程序和普通的servlet?

时间:2017-12-28 11:18:48

标签: java servlets websocket servlet-filters spring-websocket

这可以在相同的上下文中提供websocket处理程序和普通的servlet吗?

示例

http://localhost/appcontext/endpoint  --> serving by normal servlet
ws://localhost/appcontext/endpoint --> serving by websocket handler

我尝试了多种方法,但无法做到。似乎url映射是通过上下文路径过滤的,而不是像#" http'或者' ws'。可能是我发现的错误。我试图用spring和java来看这个。

1 个答案:

答案 0 :(得分:2)

简答:

不,你不能使用servlet或websocket提供的相同路径。每个http://localhost/appcontext/endpoint的http请求都应具有特定的行为

答案很长:

这个答案超出了Java范围,因为它主要依赖于RFC 6455,也就是websocket圣经。原因在于握手过程。

Websocket URIs

在RFC 6455的第3部分中,websocket URI定义如下:

  

ws-URI =" ws:" " //"主持人[":"路径["?"查询]

     

wss-URI =" wss:" " //"主持人[":"路径["?"查询]

不考虑URI细节,实际上可能认为只使用HTTP协议就可以单独访问HTTP对应物。

握手:客户端

提醒:websocket是一种双向协议。因此,客户端是初始化连接的实体。但是,一旦建立连接,客户端和服务器都可以发送消息或关闭通信。但是,服务器和客户端的概念是知道谁是谁

客户端初始化握手:"嘿服务器!我想建立一个webosocket通信"。但是,握手从http开始。在RFC 6455的第17页(第4.1节):

  
      
  1. 握手必须是[RFC2616]指定的有效HTTP请求。

  2.   
  3. 请求的方法必须是GET,HTTP版本必须至少为1.1。

         

    例如,如果WebSocket URI为&#34; ws://example.com/chat" ;,则发送的第一行应为&#34; GET / chat HTTP / 1.1&#34;。< / p>

  4.   
  5. &#34; Request-URI&#34;请求的一部分必须匹配第3节中定义的/ resource name /(相对URI),或者是绝对的http / https URI,在解析时,它具有匹配的/ resource name /,/ host /和/ port /相应的ws / wss URI。

  6.   

在每个websocket通信初始化后面隐藏了相同路径的HTTP请求。回到你的例子:

  1. 客户端询问ws://localhost/appcontext/endpoint
  2. 它实际上要求http://localhost/appcontext/endpoint提供升级请求以及RFC 6455定义的相应标头
  3. 服务器应答,并且只有握手后通信才会从http(s)切换到ws(s)
  4. 握手:服务器端

    但是,如果你想作弊并说&#34; 我假装我不知道这是一个websocket URI并且我想访问这个URL背后的HTTP资源& #34 ;.在服务器端,您的应用程序已经为URI匹配注册了路径http://localhost/appcontext/endpoint作为&#34;我在这里等待websocket连接&#34;,类似于Web服务路径匹配过程。在RFC 6455的4.2.1节中:

      

    客户的开放握手由以下部分组成。如果服务器在读取握手时发现客户端没有发送与下面描述匹配的握手(请注意,根据[RFC2616],标头字段的顺序并不重要),包括但不限于任何违规对于握手组件指定的ABNF语法,服务器必须停止处理客户端的握手并返回带有相应错误代码的HTTP响应(例如400 Bad Request)。

         
        
    1. HTTP / 1.1或更高版本的GET请求,包括&#34; Request-URI&#34; [RFC2616]应解释为第3节中定义的/资源名称(或包含/资源名称/的绝对HTTP / HTTPS URI)。

    2.   
    3. A |主持人|包含服务器权限的头字段。

    4.   
    5. An | Upgrade |包含值&#34; websocket&#34;的头字段,被视为ASCII不区分大小写的值。

    6.   

    由于http://localhost/appcontext/endpoint已注册websocket握手,因此基本HTTP请求不包含Upgrade标头,然后被服务器拒绝。

    修改

    在写这个答案时,我尝试了:

    1. 终点:appcontext/endpoint
    2. 页面:appcontext/endpoint/index.xhtml
    3. 欢迎文件:index.xhtml:所以appcontext/endpoint重定向到index.xhtml
    4. 正如预期的那样,我的websocket连接失败了。如果我将页面路径从endpoint/index.xhtml更改为endpoint2/index.xhtml,则websocket会返回。

      但是,我刚发现http://demos.kaazing.com/echo/对其websocket连接使用相同的网址,我无法找到原因&gt; _&lt;