首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有可能无缝地重定向websockets?

是否有可能无缝地重定向websockets?
EN

Stack Overflow用户
提问于 2017-10-27 04:05:00
回答 2查看 11.3K关注 0票数 12

我知道可以通过反向代理(如Nginx、HAproxy等)传递请求,但我需要将请求重定向到相同域后缀中的另一个公共服务器。即从wss://example.comwss://ws1.example.com

下面是一个示例:

我需要重定向来自Nginx或Java的请求。组织起来是可能的吗?我是否需要在客户端处理重定向,或者这段代码就足够了?

代码语言:javascript
复制
var socket = new WebSocket("wss://example.com");

socket.onopen = function() {
  alert("Connection established.");
};

socket.onclose = function(event) {
  alert('Connection closed');
};

socket.onmessage = function(event) {
  alert("Data: " + event.data);
};

socket.onerror = function(error) {
  alert("Error " + error.message);
};
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-28 12:48:23

根据webSocket specification

一旦发送了客户端的开放握手,客户端必须等待服务器的响应,然后才能发送任何进一步的数据。客户端必须验证服务器的响应,如下所示:

HTTP

  • 如果从服务器收到的状态码不是101,客户端将按照 RFC2616过程处理响应。特别是,如果客户端接收到401状态代码,它可能会执行身份验证;服务器可能会使用3xx状态代码重定向客户端(但客户端不需要遵循它们),等等。

所以,是否支持重定向完全取决于客户端,除非你在广泛的测试中发现所有相关的客户端都支持它(显然他们不支持),否则你显然不能依赖它。

您将不得不使用服务器端代理或客户端方案来手动将连接移动到另一台服务器。

票数 10
EN

Stack Overflow用户

发布于 2022-01-17 01:26:37

这个问题已经提了四年了,下面是你今天会怎么做:

在npm ws包中:

在套接字客户端构造函数(source)中将followRedirects设置为true

wscat实用程序中:

传递-L标志(source)。

在“大多数”浏览器中:

如果你不关心语义学,我对此进行wrote a package。否则,可以通过挂钩到WebSocket的构造函数来切换其构造函数中的URL,并最终支持重定向响应。

代码语言:javascript
复制
'use strict';

/* global window, WebSocket*/

(function (WebSocketNative = window.WebSocket) {
  const debug = console.log;
  debug('patching native WebSocket class to support HTTP redirects');
  window.WebSocket = class {
    constructor(url, ...args) {
      this.work = [];
      this.endpoint = url.replace(/^http/, 'ws');
      debug('ws constructed with url: "%s" and endpoint: "%s"', url, this.endpoint);
      return (
        (async () => {
          try {
            const resolver =
              window.WEBSOCKET_REDIRECT_RESOLVER || `${location.protocol}//${location.host}${location.pathname}`;
            debug('websocket address resolver: "%s"', resolver);
            const endpoint = `${resolver}?url=${encodeURIComponent(this.endpoint)}`;
            debug('resolver query endpoint: "%s"', endpoint);
            const response = await fetch(endpoint);
            debug('resolver query response: "%o"', response);
            const { dig, dug } = await response.json();
            debug('resolver dig: "%o" dug: "%o"', dig, dug);
            this.endpoint = dug;
          } finally {
            debug('websocket final endpoint: "%s"', this.endpoint);
            this.socket = new WebSocketNative(this.endpoint, ...args);
            debug('flushing %d queued operations', this.work.length);
            for (const op of this.work) op(this.socket);
          }
        })(),
        new Proxy(this, {
          get: function (target, prop) {
            debug('GETTER trace: "%s"', prop);
            switch (prop) {
              case 'construct':
              case 'endpoint':
              case 'socket':
              case 'work':
                debug('GETTER "%s" does not go through proxy', prop);
                return Reflect.get(...arguments);
              case 'OPEN':
              case 'CLOSED':
              case 'CLOSING':
              case 'CONNECTING':
                debug('GETTER "%s" is a static', prop);
                return Reflect.get(WebSocketNative, prop);
              case 'readyState':
              case 'bufferedAmount':
                return this.socket ? Reflect.get(this.socket, prop) : 0;
              case 'binaryType':
                return this.socket ? Reflect.get(this.socket, prop) : 'blob';
              case 'extensions':
              case 'protocol':
              case 'url':
                return this.socket ? Reflect.get(this.socket, prop) : '';
              default:
                return this.socket
                  ? Reflect.get(this.socket, prop)
                  : function (...args) {
                      if (target.socket) {
                        debug('socket is ready, skip queueing get "%s" with args "%o"', prop, args);
                        return Reflect.get(target.socket, prop).call(target.socket, ...args);
                      } else {
                        debug('socket is not ready yet. queueing get "%s" with args "%o"', prop, args);
                        target.work.push((socket) => Reflect.get(socket, prop).call(socket, ...args));
                      }
                    };
            }
          },
          set: function (target, prop, value) {
            debug('SETTER trace: "%s"="%o"', prop, value);
            switch (prop) {
              case 'endpoint':
              case 'socket':
              case 'work':
                return Reflect.set(...arguments);
              default:
                return this.socket
                  ? Reflect.set(this.socket, prop, value)
                  : (() => {
                      if (target.socket) {
                        debug('socket is ready, skip queueing set "%s" with value "%o"', prop, value);
                        Reflect.set(socket, prop, value);
                      } else {
                        debug('socket is not ready yet, queueing set "%s" with value "%o"', prop, value);
                        target.work.push((socket) => Reflect.set(socket, prop, value));
                      }
                      return true;
                    })();
            }
          },
        })
      );
    }
  };
})(window.WebSocket);

这段代码覆盖了浏览器的原生WebSocket类,该类支持动态地将URL切换为ALTERNATE_WEBSOCKET_ADDRESS。您需要在某个地方定义ALTERNATE_WEBSOCKET_ADDRESS,因为不可能在浏览器环境中找出重定向响应的最终URL (无论是使用fetch还是XMLHttpRequest)。fetch仅用于检测重定向。您需要想出一种机制,以便在需要重定向时让ALTERNATE_WEBSOCKET_ADDRESS准备就绪。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46962881

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档