วิธีสร้าง WebSocket URI ที่สัมพันธ์กับ URI ของเพจ


98

ฉันต้องการสร้าง WebSocket URI ที่สัมพันธ์กับ 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

"ws: //" + window.location.host + ": 6666" -done
Fattie

คำตอบ:


99

หากเว็บเซิร์ฟเวอร์ของคุณรองรับ WebSockets (หรือโมดูลตัวจัดการ WebSocket) คุณสามารถใช้โฮสต์และพอร์ตเดียวกันและเปลี่ยนรูปแบบตามที่คุณแสดงได้ มีตัวเลือกมากมายสำหรับการรันเว็บเซิร์ฟเวอร์และเซิร์ฟเวอร์ / โมดูล Websocket ร่วมกัน

ฉันขอแนะนำให้คุณดูชิ้นส่วนแต่ละชิ้นของ window.location global และรวมเข้าด้วยกันแทนที่จะทำการแทนที่ blind string

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 หรือไม่ ดังนั้นคุณอาจถูก จำกัด ว่าคุณสามารถเปลี่ยนเส้นทางในแบบที่คุณต้องการได้หรือไม่


ใช้ชื่อพา ธ ฉันได้รับ url ดังกล่าว: 'ws: // localhost: 8080 / Chat / index.html / chat' และเป็น URL ที่ไม่ปรากฏ
Denis535

1
@ wishmaster35 วิธีการจัดการจะขึ้นอยู่กับกรณีการใช้งานและการตั้งค่าของคุณ ไม่มีวิธีที่แน่นอนในการตรวจสอบว่าexample.com/part1/part2อ้างถึงไฟล์ชื่อ part2 ภายในไดเร็กทอรีชื่อ part1 หรือ wether part2 เป็นไดเร็กทอรีภายใน part1 หรือสิ่งที่แตกต่างไปจากเดิมอย่างสิ้นเชิง (เช่น part1 และ part2 เป็นคีย์ภายใน ฐานข้อมูลวัตถุ) ความหมายของ "เส้นทาง" ใน URL ขึ้นอยู่กับเว็บเซิร์ฟเวอร์และการกำหนดค่า คุณสามารถอนุมานได้ว่าสิ่งที่ลงท้ายด้วย "* .html" ควรถูกถอดออก แต่อีกครั้งสิ่งนี้จะขึ้นอยู่กับการตั้งค่าและข้อกำหนดเฉพาะของคุณ
kanaka

3
@socketpair ไม่มีพอร์ตอยู่ที่นั่น window.location.host มีชื่อโฮสต์และพอร์ต (location.hostname เป็นชื่อโฮสต์เท่านั้น)
kanaka

ฉันจะออกไปได้"/to/ws"ไหม ถ้าไม่ควรมีค่าอะไรสำหรับส่วนนั้น?
tet

1
@tet นั่นคือเส้นทางการร้องขอ GET (เช่นเส้นทาง HTTP GET) ที่ใช้เมื่อสร้างการเชื่อมต่อ WebSocket ครั้งแรก ไม่ว่าจะใช้หรือไม่ขึ้นอยู่กับการตั้งค่าของคุณ หากคุณมีเซิร์ฟเวอร์ websocket จุดประสงค์เดียว (ซึ่งอาจเกิดขึ้นเพื่อให้บริการไฟล์เว็บแบบคงที่) อาจถูกละเว้น หากคุณมีเซิร์ฟเวอร์ websocket หลายตัวหลังเว็บเซิร์ฟเวอร์เฉพาะเส้นทางอาจถูกใช้เพื่อกำหนดเส้นทางไปยังเซิร์ฟเวอร์ websocket ที่ถูกต้อง เส้นทางนี้ยังสามารถใช้เพื่อวัตถุประสงค์อื่นโดยเซิร์ฟเวอร์ websocket เช่นการส่งโทเค็น (เช่นผ่านพารามิเตอร์แบบสอบถาม) เป็นต้น
kanaka

35

นี่คือเวอร์ชันของฉันที่เพิ่มพอร์ต 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นี้:

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

14
คุณไม่จำเป็นต้องทำ port mangling เพียงแค่ใช้ location.host แทน location.hostname
kanaka

25

การใช้ 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'

ฉันจะใช้/^http/แทน'http'ในกรณีที่httpอยู่ในแถบ URL
phk

window.location.href มีเส้นทางแบบเต็มดังนั้นคุณสามารถลงเอยด้วย /page.html/path/to/ws
Eadz

อาจเป็นปัญหาได้หากตำแหน่งของคุณมี http ตัวอย่างเช่นtesthttp.com/http.html
Dániel Kis

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

2

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

0

วิธีแก้ปัญหาง่ายตาย ws และพอร์ตผ่านการทดสอบ:

var ws = new WebSocket("ws://" + window.location.host + ":6666");

ws.onopen = function() { ws.send( .. etc
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.