【问题标题】:Socket.io closed before receiving a handshake response [ECONNRESET] after a proxySocket.io 在代理后收到握手响应 [ECONNRESET] 之前关闭
【发布时间】:2015-06-18 01:00:48
【问题描述】:

我正在为 node.js 应用程序编写任务管理器。这些应用程序在任意端口中打开,因此,为了访问它们,我想伪造它们的根 像这样的网址:

http://domain.com/proxy/yourApplication

因此第三方可以向他们的应用发出 HTTP 请求,而无需知道应用在哪个端口上运行。

然后我选择了http-proxy

var express = require('express')
, router = express.Router()
, Helper = require('../helper')
, launcher = require('../launcher')
, httpProxy = require('http-proxy')
, proxy = httpProxy.createProxyServer({ws: true});

以及在该路由上侦听的代码...

// Proxy
router.use('/proxy/:name?', function(req, res) {

  var app, reqPath, referer, proxyUrl;

  // Capture the referer to proxy the request
  // in case the path is not clear enaugh
  if (req.get('referer') !== undefined) {
    var aux = req.get('referer').split('/');
    referer = aux[aux.indexOf('proxy') + 1]
  }

  // This block returns an app object
  // with the port where it is running
  app = launcher.getApp(req.params.name)
  || launcher.getApp(referer);

  if (app) {
    // Here app is running

    // In case the path is /proxy/:name
    // instead of /proxy/:name/ you need this block
    req.url = (req.url === '/') ? '' : req.url;
    reqPath = (referer !== undefined)
     ? '/' + req.params.name + req.url
     : req.url;
    req.url = reqPath.replace('/proxy/', '/');
    req.url = req.url.replace('/' + app.name, '');

    // This block of code actually pipes the request
    // to the running app and pass it to the client
    proxyUrl = req.protocol + '://localhost:' + app.port;
    proxy.web(req, res, { 
      target: proxyUrl
    });

    // Some logging
    console.log('req url: %s', req.url);
    console.log('proxy url: %s', proxyUrl);
    console.log('referer: %s', referer);

  } else {
    // Here app is not running
    res.status(404).json("App not running");
  }
});

它适用于大多数应用程序,但使用 socket.io 打开应用程序时会提示:

WebSocket connection to 'ws://localhost/proxy/xy-terminal/socket.io/1/websocket/gMqK_XRwZENuUibi4ekJ' failed: Connection closed before receiving a handshake response

在服务器控制台中...

Trace: { [Error: socket hang up] code: 'ECONNRESET' }
    at process.<anonymous> (/Users/jdario/Development/xy-dashboard/www:107:11)
    at process.emit (events.js:107:17)
    at process._fatalException (node.js:236:26)
    at ProxyServer.emit (/Users/jdario/Development/xy-dashboard/node_modules/http-proxy/node_modules/eventemitter3/index.js:75:35)
    at ClientRequest.proxyError (/Users/jdario/Development/xy-dashboard/node_modules/http-proxy/lib/http-proxy/passes/web-incoming.js:140:16)
    at ClientRequest.emit (events.js:129:20)
    at Socket.socketCloseListener (_http_client.js:247:9)
    at Socket.emit (events.js:129:20)
    at TCP.close (net.js:485:12)

由于它是伪造应用程序根目录的“代理”,我可能无法单独修改其源代码,它们应该按预期工作。在正确的端口(在本例中为 3000)打开它们时,它们不会显示任何错误。

提前谢谢你!

【问题讨论】:

  • 你知道 webSocket 连接开始是一个 http 请求,然后升级到 webSocket 协议吗?因此,您的代理需要处理这个问题,并且需要一种方法来判断 webSocket 连接的目的地是哪个应用程序。
  • 是的!实际上我认为错误可能存在,但在检查了 http-proxy 的源代码后我找不到。另外我必须注意,第一次之后的其他连接试验非常有效。第一个是点击“/proxy/appName/”时的“待处理”和到达“/proxy/appName”时的“已完成”。

标签: node.js express websocket socket.io http-proxy


【解决方案1】:

最短的答案是确实单独修改代理应用程序的源代码。所以现在他们使用

var io = require('socket.io')(http, { path: '/proxy/yourApplication'})

这篇文章解决了这个问题。 https://stackoverflow.com/a/31658307/2633577

但是,这个答案并不是最好的,因为它对托管应用程序不是 100% 透明的。

【讨论】:

    猜你喜欢
    • 2016-09-09
    • 2014-12-27
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-18
    • 1970-01-01
    • 2014-05-04
    相关资源
    最近更新 更多