Wie erstelle ich einen WebSocket-URI relativ zum Seiten-URI?

92

Ich möchte einen WebSocket-URI relativ zum Seiten-URI auf der Browserseite erstellen. Angenommen, in meinem Fall konvertieren Sie HTTP-URIs wie

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

zu

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

Was ich derzeit mache, ist, die ersten 4 Buchstaben "http" durch "ws" zu ersetzen und "/ to / ws" daran anzuhängen. Gibt es dafür einen besseren Weg?

Neuront
quelle
1
Was meinst du damit path/to/ws? Wohin führt das genau? Danke
Slevin

Antworten:

95

Wenn Ihr Webserver WebSockets (oder ein WebSocket-Handler-Modul) unterstützt, können Sie denselben Host und Port verwenden und einfach das angezeigte Schema ändern. Es gibt viele Optionen, um einen Webserver und einen Websocket-Server / ein Websocket-Modul zusammen auszuführen.

Ich würde vorschlagen, dass Sie sich die einzelnen Teile der window.location global ansehen und sie wieder zusammenfügen, anstatt eine blinde Zeichenfolge zu ersetzen.

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

Beachten Sie, dass einige Webserver (z. B. Jetty-basierte) derzeit den Pfad (anstelle des Upgrade-Headers) verwenden, um zu bestimmen, ob eine bestimmte Anforderung an den WebSocket-Handler weitergeleitet werden soll. Sie können also eingeschränkt sein, ob Sie den Pfad so transformieren können, wie Sie es möchten.

Kanaka
quelle
Unter Verwendung des Pfadnamens erhalte ich eine solche URL: 'ws: // localhost: 8080 / Chat / index.html / chat'. Und es ist unkorrelierte URL.
Denis535
1
@ wantmaster35 Wie das gehandhabt wird, hängt von Ihrem Anwendungsfall und Ihrer Einrichtung ab. Es gibt keine sichere Methode, um festzustellen, ob example.com/part1/part2 auf eine Datei mit dem Namen part2 in einem Verzeichnis namens part1 verweist oder ob part2 ein Verzeichnis in part1 oder etwas völlig anderes ist (z. B. part1 und part2 sind Schlüssel darin eine Objektdatenbank). Die Bedeutung von "Pfaden" in einer URL hängt vom Webserver und seiner Konfiguration ab. Sie könnten daraus schließen, dass alles, was mit "* .html" endet, entfernt werden sollte. Dies hängt jedoch wiederum von Ihrem spezifischen Setup und Ihren Anforderungen ab.
Kanaka
3
@socketpair nein, Port ist da. window.location.host enthält den Hostnamen und den Port (location.hostname ist nur der Hostname).
Kanaka
Kann ich weglassen "/to/ws"? Wenn nicht, welchen Wert sollte dieser Teil haben?
Tet
1
@tet Dies ist der GET-Anforderungspfad (dh der HTTP-GET-Pfad), der beim Herstellen der ersten WebSocket-Verbindung verwendet wird. Ob es verwendet wird oder nicht, hängt von Ihrem Setup ab. Wenn Sie einen Websocket-Server für einen bestimmten Zweck haben (der möglicherweise auch statische Webdateien bereitstellt), wird dieser wahrscheinlich ignoriert. Wenn sich hinter einem dedizierten Webserver mehrere Websocket-Server befinden, wird der Pfad wahrscheinlich verwendet, um zum richtigen Websocket-Server weiterzuleiten. Der Pfad kann auch für andere Zwecke durch den WebSocket - Server verwendet werden , wie zum Beispiel vorbei Token (zB über Abfrage params) usw.
kanaka
32

Hier ist meine Version, die den TCP-Port hinzufügt, falls es nicht 80 oder 443 ist:

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: Verbesserte Version wie auf Vorschlag von @kanaka:

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

Edit 2: Heutzutage erstelle ich das WebSocket:

var s = new WebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/ws");
yglodt
quelle
14
Sie müssen kein Port-Mangling durchführen, verwenden Sie einfach location.host anstelle von location.hostname
kanaka
23

Verwenden der Window.URL-API - https://developer.mozilla.org/en-US/docs/Web/API/Window/URL

Funktioniert mit http (s), Ports usw.

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
Eadz
quelle
Ich sollte erwähnen, dass dies auch mit https / wss funktioniert (ersetzen Sie 'http' durch 'ws' => 'https' => 'wss')
Eadz
7

Angenommen, Ihr WebSocket-Server überwacht denselben Port, von dem aus die Seite angefordert wird, würde ich Folgendes vorschlagen:

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

Nennen Sie es dann für Ihren Fall wie folgt:

var socket = createWebSocket(location.pathname + '/to/ws');
Pavel
quelle
location.path ist nicht korrekt. Sie sollten den Pfadnamen verwenden.
Denis535
@ Wishmaster35: Guter Fang! Fest.
Pavel
4

einfach:

location.href.replace(/^http/, 'ws') + '/to/ws'
// or if you hate regexp:
location.href.replace('http://', 'ws://').replace('https://', 'wss://') + '/to/ws'
Maksim Kostromin
quelle
Ich würde /^http/anstelle von 'http'nur für den Fall verwenden, httpist in der URL-Leiste.
phk
window.location.href enthält den vollständigen Pfad, sodass Sie am Ende /page.html/path/to/ws
Eadz erhalten können
Kann problematisch sein, wenn Ihr Standort http enthält. Zum Beispiel: testhttp.com/http.html
Dániel Kis
1
Ersetzen Sie einfach 'http: //' durch 'ws: //'. Diese einfache Idee sollte für alle Entwickler, auch für Junioren, offensichtlich sein
Maksim Kostromin
2

Auf localhost sollten Sie den Kontextpfad berücksichtigen.

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;
}
Denis535
quelle
4
Was ist der Kontextpfad?
Amirouche
1

Im Typoskript:

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

Verwendung:

alert(WebsocketUtils.websocketUrlByPath("/websocket"));
Dániel Kis
quelle