http-прокси-правила и веб-сокеты

Я не смог найти никакой документации/ответа на мои потребности.

Я в чем-то вроде рассола. Я разрабатываю приложение для веб-сокетов, которое позволит расширить модуль за счет создания новых служб (серверов веб-сокетов). Конечно, это означает больше портов для подключения. Проблема в том, что в нашей корпоративной политике открыто очень мало портов, поэтому мне нужно проксировать свои запросы.

Я читал много ответов, говорящих об использовании NGINX, но я просто не могу. Во-первых, я запускаю Windows, во-вторых, наша компания очень строга в отношении того, что можно и что нельзя использовать. Однако я могу установить любой модуль узла. Я пытался использовать модуль http-proxy вместе с http-proxy-rules.

Проблема в том, что я получаю 404 на каждый запрос веб-сокета. Отмечу, что прокси по умолчанию (для обычного веб-сервиса, а не для сокетов) работает на 100% нормально.

Вот мой текущий код:

var http = require('http'),
      httpProxy = require('http-proxy'),
      HttpProxyRules = require('http-proxy-rules');

  // Set up proxy rules instance
  var proxyRules = new HttpProxyRules({
    rules: {
      '.*/ws/admin': 'http://localhost:26266', // Rule for websocket service (admin module)
      '.*/ws/quickquery': 'http://localhost:26265' // Rule for websocket service (quickquery module)
    },
    default: 'http://Surface.levisinger.com:8080' // default target
  });

  // Create reverse proxy instance
  var proxy = httpProxy.createProxy();

  // Create http server that leverages reverse proxy instance
  // and proxy rules to proxy requests to different targets
  http.createServer(function(req, res) {

    // a match method is exposed on the proxy rules instance
    // to test a request to see if it matches against one of the specified rules
    var target = proxyRules.match(req);
    if (target) {     
      //console.log(req); 
      console.log("Returning " + target + " for " + req.headers.host);
      return proxy.web(req, res, {
        target: target,
        ws: true
      });      
    }

    res.writeHead(500, { 'Content-Type': 'text/plain' });
    res.end('The request url and path did not match any of the listed rules!');
  }).listen(5050);

Мой клиентский код, подключающийся к веб-сокету, выглядит так:

var servPath = (cliSettings["AppPaths"]["Admin"] == null) ? 'http://' + window.location.hostname + ':5050' : cliSettings["AppPaths"]["Admin"],
    AdminIO = new io(servPath, {
        extraHeaders: {
            Service: "Admin"
        },
        path: '/ws/admin'})

...

И сервер веб-сокета вызывается так:

io = require('socket.io').listen(26266,{ path: '/ws/admin'}) // can use up to 26484

Я очень надеюсь, что у кого-то здесь будет идея. Спасибо!


person Ethan    schedule 29.07.2016    source источник


Ответы (1)


Разобрался как это сделать. Для этого есть несколько вещей... 1. Вы должны использовать настраиваемые пути веб-сокетов, если хотите их проксировать. 2. Вы должны указать полный путь к веб-сокету при их проксировании. 3. Вам нужно указать событие для обработки трафика веб-сокета (ws).

Вот пример для всех вас.

+++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++

Прокси-сервер:

var   ini = require('node-ini'),
      conf = ini.parseSync('../settings/config.ini'),
      http = require('http'),
      httpProxy = require('http-proxy'),
      HttpProxyRules = require('http-proxy-rules');

  // Set up proxy rules instance
  var proxyRules = new HttpProxyRules({
    rules: {
      '.*/ws/remote': 'http://' + conf["Server"]["binding"] + ':26267/ws/remote',
      '.*/ws/admin': 'http://' + conf["Server"]["binding"] + ':26266/ws/admin', // Rule for websocket service (admin module)
      '.*/ws/quickquery': 'http://' + conf["Server"]["binding"] + ':26265/ws/quickquery' // Rule for websocket service (quickquery module)      
    },
    default: 'http://' + conf["Server"]["binding"] + ':8080' // default target
  });

  // Create reverse proxy instance
  var proxy = httpProxy.createProxy();

  // Create http server that leverages reverse proxy instance
  // and proxy rules to proxy requests to different targets
  var proxyServer = http.createServer(function(req, res) {

    // a match method is exposed on the proxy rules instance
    // to test a request to see if it matches against one of the specified rules
    var target = proxyRules.match(req);
    if (target) {     
      //console.log(req.url); 
      //console.log("Returning " + target + " for " + req.url);
      return proxy.web(req, res, {
        target: target,
        ws: true
      });      
    }

    res.writeHead(500, { 'Content-Type': 'text/plain' });
    res.end('The request url and path did not match any of the listed rules!');
  }).listen(conf["Server"]["port"]);

//
// Listen to the `upgrade` event and proxy the
// WebSocket requests as well.
//
proxyServer.on('upgrade', function (req, socket, head) {
    var target = proxyRules.match(req);
    if (target) {
        return proxy.ws(req, socket, head, { target: target });      
    }
});
process.on('SIGINT', function() {
   db.stop(function(err) {
     process.exit(err ? 1 : 0);
   });
});

Прослушиватель сокета Websocket Server:

io = require('socket.io').listen(26266,{ path: '/ws/admin'});

Подключиться к веб-сокету со страницы клиента:

AdminIO = new io({path: '/ws/admin'});

+++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++

В приведенном выше примере мое «административное» соединение, работающее на порту 26266, будет проксировано через порт 80. (Конечно, я бы рекомендовал использовать 443/SSL в любой ситуации, но это немного сложнее).

Надеюсь, это поможет кому-то!

person Ethan    schedule 01.08.2016