【问题标题】:How to construct a WebSocket URI relative to the page URI?如何构造相对于页面 URI 的 WebSocket URI?
【发布时间】:2012-05-11 12:35:51
【问题描述】:

我想在浏览器端构造一个相对于页面 URI 的 WebSocket URI。说,在我的情况下转换 HTTP URI 像

http://example.com:8000/path
https://example.com:8000/path

ws://example.com:8000/path/to/ws
wss://example.com:8000/path/to/ws

我目前正在做的是将前 4 个字母“http”替换为“ws”,并附加“/to/ws”。有没有更好的办法呢?

【问题讨论】:

  • path/to/ws 是什么意思?这究竟会导致什么?谢谢
  • "ws://" + window.location.host + ":6666" -done

标签: websocket uri relative-path


【解决方案1】:

如果您的 Web 服务器支持 WebSockets(或 WebSocket 处理程序模块),那么您可以使用相同的主机和端口,并像您展示的那样更改方案。有很多选项可以同时运行 Web 服务器和 Websocket 服务器/模块。

我建议您查看 window.location 全局的各个部分并将它们重新组合在一起,而不是进行盲字符串替换。

var loc = window.location, new_uri;
if (loc.protocol === "https:") {
    new_uri = "wss:";
} else {
    new_uri = "ws:";
}
new_uri += "//" + loc.host;
new_uri += loc.pathname + "/to/ws";

请注意,某些 Web 服务器(即基于 Jetty 的服务器)当前使用路径(而不是升级标头)来确定是否应将特定请求传递给 WebSocket 处理程序。因此,您可能会受限于是否可以按照您想要的方式转换路径。

【讨论】:

  • 使用路径名我得到这样的 url:'ws://localhost:8080/Chat/index.html/chat'。这是不正确的网址。
  • @wishmaster35 如何处理将取决于您的用例和设置。没有可靠的方法来确定 example.com/part1/part2 是否引用名为 part1 的目录中名为 part2 的文件,或者 part2 是 part1 中的目录,还是完全不同的东西(例如 part1 和 part2 是对象数据库中的键) . URL 中“路径”的含义取决于 Web 服务器及其配置。你可以推断出任何以“*.html”结尾的东西都应该被去掉。但同样,这将取决于您的具体设置和要求。
  • @socketpair 不,端口在那里。 window.location.host 包含主机名和端口(location.hostname 只是主机名)。
  • 我可以省略"/to/ws" 吗?如果不是,那部分的价值应该是多少?
  • @tet 是建立初始 WebSocket 连接时使用的 GET 请求路径(即 HTTP GET 路径)。是否使用取决于您的设置。如果您有一个单一用途的 websocket 服务器(可能碰巧也提供静态 web 文件),那么它可能会被忽略。如果您在专用 Web 服务器后面有多个 WebSocket 服务器,则该路径可能用于路由到正确的 WebSocket 服务器。该路径还可以被 websocket 服务器用于其他目的,例如传递令牌(例如通过查询参数)等。
【解决方案2】:

简单的解决方案,ws 和 port,经过测试:

var ws = new WebSocket("ws://" + window.location.host + ":6666");

ws.onopen = function() { ws.send( .. etc

【讨论】:

    【解决方案3】:

    简单:

    location.href.replace(/^http/, 'ws') + '/to/ws'
    // or if you hate regexp:
    location.href.replace('http://', 'ws://').replace('https://', 'wss://') + '/to/ws'
    

    【讨论】:

    • 我会使用/^http/而不是'http',以防http在网址栏中。
    • window.location.href 包含完整路径,因此您最终可能会得到 /page.html/path/to/ws
    • 如果您的位置包含 http,则可能会出现问题。例如:testhttp.com/http.html
    • 只需将“http://”替换为“ws://”,这个简单的想法对于任何开发人员,甚至是初级开发人员都应该是显而易见的
    【解决方案4】:

    在打字稿中:

    export class WebsocketUtils {
    
        public static websocketUrlByPath(path) {
            return this.websocketProtocolByLocation() +
                window.location.hostname +
                this.websocketPortWithColonByLocation() +
                window.location.pathname +
                path;
        }
    
        private static websocketProtocolByLocation() {
            return window.location.protocol === "https:" ? "wss://" : "ws://";
        }
    
        private static websocketPortWithColonByLocation() {
            const defaultPort = window.location.protocol === "https:" ? "443" : "80";
            if (window.location.port !== defaultPort) {
                return ":" + window.location.port;
            } else {
                return "";
            }
        }
    }
    

    用法:

    alert(WebsocketUtils.websocketUrlByPath("/websocket"));
    

    【讨论】:

      【解决方案5】:

      使用 Window.URL API - https://developer.mozilla.org/en-US/docs/Web/API/Window/URL

      适用于 http(s)、端口等

      var url = new URL('/path/to/websocket', window.location.href);
      
      url.protocol = url.protocol.replace('http', 'ws');
      
      url.href // => ws://www.example.com:9999/path/to/websocket
      

      【讨论】:

      • 我应该提一下,这也适用于 https/wss(将 'http' 替换为 'ws' => 'https' => 'wss' )
      【解决方案6】:

      这是我的版本,它添加了 tcp 端口,以防它不是 80 或 443:

      function url(s) {
          var l = window.location;
          return ((l.protocol === "https:") ? "wss://" : "ws://") + l.hostname + (((l.port != 80) && (l.port != 443)) ? ":" + l.port : "") + l.pathname + s;
      }
      

      编辑 1:根据@kanaka 的建议改进版本:

      function url(s) {
          var l = window.location;
          return ((l.protocol === "https:") ? "wss://" : "ws://") + l.host + l.pathname + s;
      }
      

      编辑 2:现在我创建了 WebSocket 这个:

      var s = new WebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/ws");
      

      【讨论】:

      • 你不需要做端口修改,只需使用 location.host 而不是 location.hostname
      【解决方案7】:

      在本地主机上,您应该考虑上下文路径。

      function wsURL(path) {
          var protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
          var url = protocol + location.host;
          if(location.hostname === 'localhost') {
              url += '/' + location.pathname.split('/')[1]; // add context path
          }
          return url + path;
      }
      

      【讨论】:

      • 什么是上下文路径?
      【解决方案8】:

      假设您的 WebSocket 服务器正在侦听与请求页面相同的端口,我建议:

      function createWebSocket(path) {
          var protocolPrefix = (window.location.protocol === 'https:') ? 'wss:' : 'ws:';
          return new WebSocket(protocolPrefix + '//' + location.host + path);
      }
      

      然后,根据您的情况,将其命名如下:

      var socket = createWebSocket(location.pathname + '/to/ws');
      

      【讨论】:

        猜你喜欢
        • 2011-07-30
        • 2022-12-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-11
        • 1970-01-01
        • 2017-01-11
        • 2020-04-01
        相关资源
        最近更新 更多