Как построить URI WebSocket относительно URI страницы?


Я хочу построить 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". Есть ли лучший способ для этого?

7 73

7 ответов:

Если ваш веб-сервер поддерживает WebSockets (или модуль обработчика WebSocket), то вы можете использовать тот же хост и порт и просто изменить схему, как вы показываете. Есть много вариантов для запуска веб-сервера и Websocket server / module вместе.

Я бы предложил вам посмотреть на отдельные части окна.расположение глобальное и объединить их вместе вместо того, чтобы делать слепую подстановку строк.

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

обратите внимание, что некоторые веб-сервера (т. е. Jetty based ones) в настоящее время используют путь (а не заголовок обновления), чтобы определить, должен ли конкретный запрос быть передан обработчику WebSocket. Таким образом, вы можете быть ограничены в том, Можете ли вы преобразовать путь так, как вы хотите.

вот моя версия, которая добавляет порт 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;
}

Edit 1: улучшенная версия, как по предложению @kanaka:

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

Edit 2: В настоящее время я создаю WebSocket это:

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

предполагая, что ваш сервер 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');

через окно.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

на localhost, вы должны рассмотреть контекстный путь.

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

в машинописный текст:

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

просто:

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