Использование node http-proxy для прокси-соединений в сети

У меня есть приложение, которое использует websockets через socket.io. Для моего приложения я хотел бы использовать отдельный HTTP-сервер для обслуживания статического контента и JavaScript для моего приложения. Поэтому мне нужно установить прокси-сервер.

Я использую node-http-proxy. В качестве отправной точки у меня есть приложение для веб-приложений, работающее на порту 8081. Я использую следующий код для перенаправления связи socket.io на этот автономный сервер, используя экспресс для обслуживания статического содержимого:

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

// create a server
var app = express();
var proxy = httpProxy.createProxyServer({ ws: true });

// proxy HTTP GET / POST
app.get('/socket.io/*', function(req, res) {
  console.log("proxying GET request", req.url);
  proxy.web(req, res, { target: 'http://localhost:8081'});
});
app.post('/socket.io/*', function(req, res) {
  console.log("proxying POST request", req.url);
  proxy.web(req, res, { target: 'http://localhost:8081'});
});

// Proxy websockets
app.on('upgrade', function (req, socket, head) {
  console.log("proxying upgrade request", req.url);
  proxy.ws(req, socket, head);
});

// serve static content
app.use('/', express.static(__dirname + "/public"));

app.listen(8080);

Приведенное выше приложение работает очень хорошо, однако я вижу, что socket.io больше не использует веб-сайты, а вместо этого возвращается к опросу XHR.

Я могу подтвердить это, просмотрев журналы из прокси-кода:

proxying GET request /socket.io/1/?t=1391781619101
proxying GET request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=13917816294
proxying POST request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=1391781629
proxying GET request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=13917816294
proxying GET request /socket.io/1/xhr-polling/f-VVzPcV-7_IKJJtl6VN?t=13917816294

Кто-нибудь знает, как проксировать связь с веб-сокетами? Все примеры из node-http-proxy предполагают, что вы хотите проксировать весь трафик, а не проксировать некоторых и обслуживать других.

Ответ 1

Просто наткнулся на ваш вопрос, и я вижу, что на него все еще не ответил. Ну, если вы все еще ищете решение... Проблема в вашем коде заключается в том, что app.listen(8080) является просто синтаксическим сахаром для

require('http').createServer(app).listen(8080)

а сам app - это просто функция обработчика, а не экземпляр httpServer (я лично считаю, что эту функцию следует удалить из Express, чтобы избежать путаницы). Таким образом, ваш app.on('upgrade') на самом деле никогда не используется. Вместо этого вы должны написать

var server = require('http').createServer(app);
server.on('upgrade', function (req, socket, head) {
  proxy.ws(req, socket, head);
});
server.listen(8080);

Надеюсь, это поможет.

Ответ 2

Вам нужны оба сервера? Если нет, вы можете использовать один и тот же сервер для статических файлов и прослушивать соединения сокетов:

// make the http server
var express = require('express'),
    app = express(), server = require('http').createServer(app),
    io;

// serve static content
server.use('/', express.static(__dirname + '/public'));

server.listen(8080);

// listen for socket connections
io = require('socket.io').listen(server);

// socket stuff here