2013-06-24 4 views
11

Я пытаюсь сделать socket.io работать как на http, так и на https соединениях, но похоже, что с моей конфигурацией он может работать только на одном из них.Используйте как http, так и https для socket.io

С помощью следующих опций конфигурации socket.io может получить доступ к моему приложению через https, но при попытке доступа через обычный http он не может подключиться, и я получаю ошибки.

var app = express() 
    , http= require('http').createServer(app) 
    , https = require('https').createServer(options, app) 
    , io = require('socket.io').listen(https, { log: false }) 

И потом у меня есть этот

http.listen(80, serverAddress); 
https.listen(443, serverAddress); 

На стороне клиента у меня есть это:

<script src='/socket.io/socket.io.js'></script> 

var socket = io.connect('https://<%= serverAddress %>', {secure: true, 'sync disconnect on unload' : true}); 

Конечно, если я переключить HTTP с параметрами HTTPS на функции .listen и .connect сервера и клиента соответственно, я получаю обратные результаты. Socket.io может получить доступ через http, а не через https.

Как это можно достичь? Мне это нужно в основном потому, что речь идет о приложении facebook, поэтому он должен предоставлять как http, так и https-соединения в соответствии с правилами facebook.

Edit: В случае, если это помогает о проблеме, ошибки я получаю это ниже

Failed to load resource: the server responded with a status of 404 (Not Found) http://DOMAIN/socket.io/socket.io.js 

И из-за этого я получаю другие, такие как:

Uncaught ReferenceError: io is not defined 

ответ

2

я сделал что-то аналогично, и потребовалось два экземпляра socket.io. Что-то вроде этого:

var express = require('express'); 
var oneServer = express.createServer(); 
var anotherServer = express.createServer(); 
var io = require('socket.io'); 

var oneIo = io.listen(oneServer); 
var anotherIo = io.listen(anotherServer); 

Конечно, вам нужно дважды вводить сообщения: для обоих экземпляров socket.io.

Хорошим вариантом является делегирование SSL-обработкой до stunnel и забыть о SSL в вашем коде.

+0

Будет ли клиент из 'http' связываться с кем-либо, связанным с' https'? Что касается 'stunnel', я пробовал его, а также' http-proxy', но я не мог заставить их работать правильно. Можете ли вы привести пример для любого из них? –

+0

Извините за задержку. Да, stunnel заботится о SSL и прозрачно расшифровывает ваших клиентов, подключенных к порту https (443), чтобы они отображались как подключенные к экспресс-порту http (80). – MrTorture

+0

Вот сущность с простой простой конфигурацией для stunnel, которая прослушивает 443 и пересылает весь входящий трафик на порт 80 одного и того же хоста: https://gist.github.com/mbenedettini/5911415 – MrTorture

0

Я угадываю, что запросы на поиск кроны могут быть причиной, по которой вы получаете ошибки. Изменение протокола считается изменением в домене. Поэтому для страницы, обслуживаемой через сервер http, доступ к серверу https (сервер веб-сервера, прикрепленный к нему), может вызывать ошибки безопасности. См. Пример here о том, как включить CORS в экспресс.

Также вы должны изменить * в заголовке на http://serverAddress , https://serverAddress. Разрешить все сайты не очень хорошая идея, использовать его для тестирования.

То же самое верно, если вы пытаетесь использовать AJAX между серверами http и . Пожалуйста, опубликуйте ошибки, просто чтобы быть уверенным в этом.

+0

Спасибо, я добавил ошибки i Получать. Я попытался включить CORS, и тогда я понял, что способ, которым я включил socket.io в 'head' на стороне клиента, должен измениться, так как запрос всегда относится к htpps, а не к URL-адресу. Однако это не сработало, я получил некоторые другие ошибки, такие как «NETWORK_ERR: XMLHttpRequest Exception 101», это должно быть потому, что я использую Websockets и, если недоступен, опрос XHR. –

+0

Произошла ли эта ошибка после ошибок, добавленных вами, или те ошибки, которые вы добавили, были заменены этой ошибкой. – user568109

+0

Эта ошибка заменила начальную. –

4

Возможно, серверный объект node.js для HTTP и HTTPS должен иметь возможность прослушивать произвольное количество портов и интерфейсов с использованием и без SSL, но в настоящее время это не выполняется. (Я смог получить один сервер для прослушивания на двух портах, передав второй сервер, у которого не было приемника запросов в качестве аргумента «handle» для интерфейса server.listen (handle, [callback]), в дополнение к server.listen (порт , [имя хоста], [отставание], [вызов]), но он не работает с SSL/не-SSL серверов смешанных.)

Stunnel обходной путь уже упоминалось, конечно, является жизнеспособным вариантом, но если не желательно устанавливать отдельную часть программного обеспечения (чтобы избежать зависимостей от non-node.js), одно и то же туннелирование может быть выполнено изначально в node.js вместо этого (при условии, что HTTP на порту 80 и HTTPS на порту 443):

var fs = require('fs'); 
var net = require('net'); 
var tls = require('tls'); 
var sslOptions = { 
    key: fs.readFileSync('server-key.pem'), 
    cert: fs.readFileSync('server-cert.pem') 
}; 
tls.createServer(sslOptions, function (cleartextStream) { 
    var cleartextRequest = net.connect({ 
     port: 80, 
     host: '127.0.0.1' 
    }, function() { 
     cleartextStream.pipe(cleartextRequest); 
     cleartextRequest.pipe(cleartextStream); 
    }); 
}).listen(443); 

Это будет иметь такой же эффект, как использование stunnel. Другими словами, это позволит избежать необходимости в двух отдельных экземплярах сервера socket.io, а также сделать модуль node.js «https» избыточным.

13

Я считаю, что проблема заключается в вашем способе настройки socket.io на стороне сервера и на клиенте.

Вот как я сделал это работу (только для вас).

Сервер:

var debug = require('debug')('httpssetuid'); 
var app = require('../app'); 
var http = require('http'); 
var https = require('https'); 
var fs = require('fs'); 
var exec = require('child_process').exec; 
var EventEmitter = require('events').EventEmitter; 
var ioServer = require('socket.io'); 

var startupItems = []; 
startupItems.httpServerReady = false; 
startupItems.httpsServerReady = false; 

var ee = new EventEmitter(); 

ee.on('ready', function(arg) { 
    startupItems[arg] = true; 
    if (startupItems.httpServerReady && startupItems.httpsServerReady) { 
    var id = exec('id -u ' + process.env.SUDO_UID, function(error, stdout, stderr) { 
     if(error || stderr) throw new Error(error || stderr); 
     var uid = parseInt(stdout); 
     process.setuid(uid); 
     console.log('de-escalated privileges. now running as %d', uid); 
     setInterval(function cb(){ 
     var rnd = Math.random(); 
     console.log('emitting update: %d', rnd); 
     io.emit('update', rnd); 
     }, 5000); 
    }); 
    }; 
}); 

app.set('http_port', process.env.PORT || 80); 
app.set('https_port', process.env.HTTPS_PORT || 443); 

var httpServer = http.createServer(app); 

var opts = { 
    pfx: fs.readFileSync('httpssetuid.pfx') 
}; 
var httpsServer = https.createServer(opts, app); 

var io = new ioServer(); 

httpServer.listen(app.get('http_port'), function(){ 
    console.log('httpServer listening on port %d', app.get('http_port')); 
    ee.emit('ready', 'httpServerReady'); 
}); 

httpsServer.listen(app.get('https_port'), function(){ 
    console.log('httpsServer listening on port %d', app.get('https_port')); 
    ee.emit('ready', 'httpsServerReady'); 
}); 

io.attach(httpServer); 
io.attach(httpsServer); 

io.on('connection', function(socket){ 
    console.log('socket connected: %s', socket.id); 
}); 

Клиент:

script(src='/socket.io/socket.io.js') 
script. 
    var socket = io(); 
    socket.on('update', function(update){ 
    document.getElementById('update').innerHTML = update; 
    }); 

Вот ключевые моменты для сервера:

  1. требуют socket.io, но не называют это метод прослушивания (предполагается, что http и https являются уже требуется). Вместо этого просто держите ссылку. (Вар ioServer = требуется ('Socket.io'))
  2. создать ваш HTTP & HTTPS сервер
  3. создать новый экземпляр ioServer
  4. связать ваши HTTP и HTTPS серверов (.listen)
  5. присоединять HTTP & https-сервера в экземпляр io. (.listen является псевдонимом для .attach)
  6. Настройка событий io.

И клиент (синтаксис нефрита, но вы получите идею):

  1. включают Socket.io сценарий тег
  2. вызова Ио и захвата опорного
  3. установки обработчиков событий

На клиенте вам не нужно вызывать io.connect(). Кроме того, я не уверен в ваших вариантах. Похоже, у вас есть typo (,,), и я не могу найти ссылку на secure: true в документации 1.0.