如何构造相对于页面URI的WebSocket URI?


92

我想在浏览器端构造一个相对于页面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

我目前正在做的是用“ ws”替换前四个字母“ http”,并在其后附加“ / to / ws”。有什么更好的办法吗?


1
你是什么意思path/to/ws?这到底在哪里?谢谢
slevin 2014年

Answers:


95

如果您的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'。这是错误的网址。
Denis535

1
@ wishmaster35如何处理将取决于您的用例和设置。没有确定的方法可以确定example.com/part1/part2是否引用了名为part1的目录中名为part2的文件,或者part2是part1内的目录,还是完全不同的文件(例如part1和part2是其中的键)对象数据库)。URL中“路径”的含义取决于Web服务器及其配置。您可以推断所有以“ * .html”结尾的内容都应删除。但这又取决于您的特定设置和要求。
kanaka 2015年

3
@socketpair不,端口在那里。window.location.host包含主机名和端口(location.hostname仅是主机名)。
kanaka 2015年

我可以离开"/to/ws"吗?如果没有,那部分的价值是多少?
tet

1
@tet是建立初始WebSocket连接时使用的GET请求路径(即HTTP GET路径)。是否使用它取决于您的设置。如果您有一个单一用途的websocket服务器(可能恰好还提供静态Web文件),则可能会忽略它。如果在专用Web服务器后面有多个Websocket服务器,则该路径可能用于路由到正确的Websocket服务器。该路径还可以由websocket服务器用于其他目的,例如传递令牌(例如,通过查询参数)等
。– kanaka

32

这是我的版本,如果不是80或443,则会添加tcp端口:

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");

14
您不需要进行端口处理,只需使用location.host而不是location.hostname
kanaka 2015年

24

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

可与http,端口等配合使用。

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(用'ws'=>'https'=>'wss'替换'http')
Eadz

7

假设您的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');

location.path不正确。您应该使用路径名。
Denis535

@ wishmaster35:很好!固定。
帕维尔(Pavel)2015年

4

简单:

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是在URL栏内。
phk

window.location.href包含完整路径,因此您可以结束/page.html/path/to/ws
Eadz

如果您的位置包含http,可能会出现问题。例如:testhttp.com/http.html
Kis

1
只需将'http://'替换为'ws://',对于任何开发人员,甚至对于初级开发人员来说,简单的想法都应该显而易见
Maksim Kostromin

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;
}

4
什么是上下文路径?
amirouche

1

在打字稿中:

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"));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.