108

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

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”附加到它上面。有没有更好的方法呢?

4

8 回答 8

111

如果您的 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 处理程序。因此,您可能会受限于是否可以按照您想要的方式转换路径。

于 2012-05-02T16:39:02.513 回答
42

这是我的版本,它添加了 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");
于 2013-11-23T11:06:00.843 回答
33

使用 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
于 2017-11-24T11:59:44.353 回答
9

假设您的 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');
于 2015-07-09T16:24:01.740 回答
6

简单的:

location.href.replace(/^http/, 'ws') + '/to/ws'
// or if you hate regexp:
location.href.replace('http://', 'ws://').replace('https://', 'wss://') + '/to/ws'
于 2017-05-07T23:35:09.670 回答
2

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

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;
}
于 2015-10-25T18:30:38.583 回答
2

在打字稿中:

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"));
于 2017-12-02T17:51:03.350 回答
0

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

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

ws.onopen = function() { ws.send( .. etc
于 2020-10-14T17:24:39.430 回答