node.js - WebSocket 代理在 Node.js 和 Angular 上失败。意外响应代码 : 404

标签 node.js angular websocket proxy

我正在尝试加快代理 Websocket 的速度。我有一些从教程中修改的 Angular 代码,该教程根据 echo.websocket.org 测试 websocket 连接。该代码本身运行良好。

<!DOCTYPE html>
<html>
   <meta charset = "utf-8" />
   <title>WebSocket Test</title>

   <script language = "javascript" type = "text/javascript">
      var wsUri = "ws://echo.websocket.org/";
      //var wsUri = "ws://localhost:8015"
      var output;
      var success = 0;
      var failure = 0;

      function init() {

        output = document.getElementById("output");
         output.innerHTML = "";
         testWebSocket();
         writeScore();

      }


      function testWebSocket() {
         websocket = new WebSocket(wsUri);

         websocket.onopen = function(evt) {
            onOpen(evt)
         };

         websocket.onclose = function(evt) {
            onClose(evt)
         };

         websocket.onmessage = function(evt) {
            onMessage(evt)
         };

         websocket.onerror = function(evt) {
            onError(evt)
         };
      }

      function onOpen(evt) {
         writeToScreen("CONNECTED");
         doSend("WebSocket rocks");
         success = success +1;
      }

     function onClose(evt) {
         writeToScreen("DISCONNECTED");
      }

      function onMessage(evt) {
         writeToScreen('<span style = "color: blue;">RESPONSE: ' + 
            evt.data+'</span>'); websocket.close();
      }

      function onError(evt) {
         writeToScreen('<span style = "color: red;">ERROR:</span> '
            + evt.data);
        failure = failure +1;
      } 

      function doSend(message) {
         writeToScreen("SENT: " + message); websocket.send(message);
      }

      function writeToScreen(message) {
         var pre = document.createElement("p"); 
         pre.style.wordWrap = "break-word"; 
         pre.innerHTML = message; 
         output.appendChild(pre);
      }

        function writeScore(){

        var pScore = document.createElement("p");
        pScore.style.wordWrap = "break-word";
        pScore.innerHTML = "Success   "+ success+ "   Failures   "+ failure;
        output.appendChild(pScore);

        }

      window.addEventListener("load", init, false);
   </script>

   <h2>WebSocket Test</h2>
   <div id = "output"></div>

</html>

按照 https://github.com/nodejitsu/node-http-proxy#proxying-websockets 的说明进行操作

我尝试通过两种不同的方式设置一个简单的代理,通过更改 Angular 代码中的 wsUri 变量以指向在中创建的服务器之一,将 Angular 页面的 websocket 请求转发到相同的 echo.websocket.org 连接这段代码。

///
// Setup our server to proxy standard HTTP requests
//

var httpProxy = require('http-proxy');
var http = require('http');

var proxy = new httpProxy.createProxyServer({
  target: {
    host: 'echo.websocket.org',
    port: 80
  }
});


var proxyServer = http.createServer(function (req, res) {
  proxy.web(req, res);
});

//
// Listen to the `upgrade` event and proxy the
// WebSocket requests as well.
//
proxyServer.on('upgrade', function (req, socket, head) {
        console.log(socket);
        proxy.ws(req, socket, head);
});


proxyServer.listen(8015);

var test = httpProxy.createServer({
  target: 'ws://echo.websocket.org',
  ws: true
});

test.listen(8014);

不幸的是,代理请求(对于在端口 8014 和 8015 上监听的服务器)触发了 Angular websocket.onerror 事件处理程序,为我提供了一条不太有用的 evt.data 的“未定义”消息。

更新:

当我尝试使用本地主机代理打开网页时,Chrome 在开发人员工具中显示以下错误消息。

index.htm:29 WebSocket connection to 'ws://localhost:8015/' failed: Error during WebSocket handshake: Unexpected response code: 404

Firefox 在其“Web 控制台”中显示以下内容

Firefox can’t establish a connection to the server at ws://localhost:8015/.

但是,升级事件正在触发,因为我看到 Node 的控制台显示 Node JS 代码的 console.log() 行中的套接字信息。这让我相信本地主机服务器已被找到,从而引发了 404 错误的起源问题。我不确定它是否与查找代理(触发其http升级事件)或代理的目标有关。

当浏览器和 echo.websocket.org 之间没有代理时,如何让 Node JS 代理 Angular Websocket 连接,该连接可以正常工作?

最佳答案

TLDR; 它与转发代理请求之前设置 Host: foo.com header 有关。

基本上,WebSocket 握手期间出错:意外的响应代码:404 意味着它实际上无法与给定的 wsUri 建立任何连接。

this issue 可以看出, changeOrigin 建议默认为 true

但是,在我们的例子中它是false(默认情况下)。因此,如果没有正确设置 HTTP Host header ,转发的请求将无效/格式错误。 您可以尝试进一步调试以查看真实的 HTTP 属性、 header 等。

另外,

autoRewrite attribute rewrites the location host/port on (201/301/302/307/308) redirects based on requested host/port.

尝试添加以下属性作为 createServer() 参数:

autoRewrite: true,
changeOrigin: true,

所以,它变成:

const test = httpProxy.createServer({
  target: 'ws://echo.websocket.org',
  ws: true,
  autoRewrite: true,
  changeOrigin: true,
});

test.listen(8014);

希望对你有帮助!

关于node.js - WebSocket 代理在 Node.js 和 Angular 上失败。意外响应代码 : 404,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50610344/

相关文章:

JavaScript split 为空字符串赋予数组大小 1,而不是 0

node.js - var 套接字 = io.connect ('http://yourhostname/' );?

angular - 如何在 Visual Studio Code(热键)中格式化文件?

angular - 如何使用我的 ionic 2 应用程序打开 android 手机的安全设置?

node.js - 在另一个平台(Grails)旁边使用 Node.js

android - 无法启动服务器 QWsServer 错误 : The address is protected

java - 哪种websocket服务器实现可以与rabbitmq结合使用?

json - Node.js:从Elasticsearch查询中解析JSON对象

node.js - 我的express.js hello世界和Docker安装程序在做什么?

Angular - 使用 routerlink 将对象传递给 @Input 参数