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

Я хочу создать URI WebSocket относительно URI страницы на стороне браузера. Скажем, в моем случае конвертировать URI HTTP, например

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

Ответ 1

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

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

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) в настоящее время используют путь (а не заголовок обновления), чтобы определить, должен ли конкретный запрос передаваться обработчику WebSocket. Таким образом, вы можете быть ограничены тем, можете ли вы преобразовать путь так, как вы хотите.

Ответ 2

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

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

Ответ 3

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

Ответ 4

На локальном хосте вы должны рассмотреть путь контекста.

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

Ответ 5

легко:

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

Ответ 6

Использование API Window.URL - 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

Ответ 7

В typescript:

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