ページ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

私が現在行っていることは、最初の4文字の「http」を「ws」に置き換え、それに「/ to / ws」を追加することです。そのためのより良い方法はありますか?


1
どういう意味path/to/wsですか?これは正確にどこにつながるのですか?ありがとう
slevin 2014年

回答:


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ハンドラーに渡すかどうかを決定しています。したがって、パスを希望どおりに変換できるかどうかに制限がある場合があります。


パス名を使用して、「ws:// localhost:8080 / Chat / index.html / chat」のようなURLを取得します。そして、それは正しいURLではありません。
Denis535

1
@ wishmaster35それがどのように処理されるかは、ユースケースとセットアップに依存します。example.com/part1/part2が part1と呼ばれるディレクトリ内のpart2という名前のファイルを参照しているか、part2がpart1内のディレクトリか、またはまったく異なるものか(たとえば、part1とpart2がオブジェクトデータベース)。URLの「パス」の意味は、Webサーバーとその構成次第です。「* .html」で終わるものはすべて削除する必要があると推測できます。ただし、これは特定のセットアップと要件によって異なります。
akaaka 2015年

3
@socketpairいいえ、ポートはあります。window.location.hostには、ホスト名とポートが含まれます(location.hostnameはホスト名のみです)。
カナカ2015年

除外できます"/to/ws"か?そうでない場合、その部分の値は何であるべきですか?
tet

1
@tetこれは、最初のWebSocket接続が確立されたときに使用されるGETリクエストパス(つまり、HTTP GETパス)です。使用するかどうかは、セットアップによって異なります。単一目的のWebSocketサーバーを使用している場合(静的Webファイルも処理する可能性があります)、おそらく無視されます。専用のWebサーバーの背後に複数のWebSocketサーバーがある場合、パスはおそらく正しいWebSocketサーバーへのルーティングに使用されています。パスは等通過するトークン(例えば介してクエリparamsは)、などの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.hostnameの代わりにlocation.hostを使用してください
kanaka

24

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

これはhttps / wssでも機能することを言及する必要があります( 'http'を 'ws'に置き換えます=> 'https' => 'wss')
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

4

簡単:

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

URLバーの中にある場合に備えて、/^http/代わりに使用します。'http'http
2017年

window.location.hrefには完全なパスが含まれているため、最終的には/page.html/path/to/ws
Eadz

場所にhttpが含まれている場合、問題が発生する可能性があります。例えば:testhttp.com/http.html
ダニエル・キシュ

1
「http://」を「ws://」に置き換えるだけで、簡単なアイデアが開発者、さらにはジュニアにも明らかであるはずです
Maksim Kostromin

2

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

4
コンテキストパスとは
amirouche 2017年

1

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"));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.