Задать вопрос
@sorokinfil

Как заставить работать прокси socket.io через nginx на Ubuntu?

Здравствуйте. Есть сайт, находится на локальном сервере на Ubuntu 18.04. Работает на nginx + php-fpm + node.js для работы интерактивных элементов через socket.io. Версии: nginx 1.14.0, node.js 8.10.0, остальное, наверно, не важно.

Пытаюсь настроить прокси socket.io (node.js) через nginx. Всё, вроде, сделал правильно, и, конечно же, ничего не работает. Браузер не выводит никаких ошибок, нода тоже не подаёт вида, что получает соединения по сокету.

Без прокси нода прекрасно работает. Но без прокси обойтись нельзя, так как будет ssl, а если node.js и nginx работают независимо, то браузер полагает, что https://site.local и https://site.local:3000 - это разные источники, даже если я передаю заголовок 'Access-Control-Allow-Origin: *', и не позволяет соединиться с нодой. Сертификаты самоподписанные для тестов, но даже если выключить везде-везде ssl, то нет никакого результата.

Вопрос: каким катком по всему этому проехать, чтобы оно начало работать так, как должно? Сразу предупреждаю, что в Ubuntu и nginx не силён, и прошу подробные ответы, что и где поменять.

Актуализация 1
Изменил location для обращения к сокету с /ws/ на /socket.io/. В вопросе также заменил. На ноду стали приходить emit'ы при дисконнекте клиента. Любые другие emit'ы по-прежнему не доходят. Временно выключил https на nginx и включил логирование ошибок. Вот такая ошибка всплывает несколько раз:

2019/01/19 00:47:11 [error] 18590#18590: *4011 upstream prematurely closed connection while reading response header from upstream, client: 127.0.0.1, server: site.local, request: "GET /socket.io/?EIO=3&transport=polling&t=MXYxf2D HTTP/1.1", upstream: "127.0.0.1:3000/?EIO=3&transport=polling&t=MXYxf2D", host: "site.local", referrer: "site.local/tasks"

2019/01/19 00:47:12 [error] 18590#18590: *4011 connect() failed (111: Connection refused) while connecting to upstream, client: 127.0.0.1, server: site.local, request: "GET /socket.io/?EIO=3&transport=polling&t=MXYxg6A HTTP/1.1", upstream: "127.0.0.1:3000/?EIO=3&transport=polling&t=MXYxg6A", host: "site.local", referrer: "site.local/tasks"


Код из /etc/nginx/sites-available/site.local:
# ...

upstream nodejs # типа переменной, содержащей адрес сервера с нодой
{
	ip_hash;
	server localhost:3000; # пытался менять порты, писать адрес сайта напрямую и ip, бесполезно
}

server
{
	# Порт, SSL и ключи, сервер, директория
	listen 443 ssl;
	ssl_certificate /home/user/sites/site.local/ssl/server.crt;
	ssl_certificate_key /home/user/sites/site.local/ssl/server.key;
	server_name site.local;
	root /home/user/sites/site.local;
	index index.php;
	
	# ...
	
	# Пытаемся открыть путь, как файл, как каталог, и если нет, то перенаправляем на index.php
	location /
	{
		try_files $uri $uri/ /index.php?$query_string;
	}

	# Подключение php-fpm
	location ~* \.php$
	{
		include snippets/fastcgi-php.conf;
		fastcgi_pass unix:/run/php/php7.2-fpm.sock;
	}

	# Прокси socket.io (https://site.local/socket.io/)
	location /socket.io/
	{
		# Перенаправление на upstream nodejs из начала листинга
		proxy_pass http://nodejs;
		
		# Тут по-всякому игрался, никакого толка
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $host;
		proxy_connect_timeout 60s;
		proxy_read_timeout 60s;
		proxy_send_timeout 60s;
	}

	# ...

}


Код из server.js (Node.js)
// ...

// Инициализация сервера, тут вроде ок
var http = require ('http');
var io = require ('socket.io');
var app = http.createServer ().listen (3000);
var io = io.listen (app);

// ...

// Пункты назначения после проксирования, до которых ничего не доходит
io.sockets.on ('connection', function (socket)
{
	// Авторизация
	socket.on ('Auth_Request', function (data)
	{
		console.log ('какого чёрта не выводится консоле.лог?');
	});
	
	// Отключение
	socket.on ('disconnect', function ()
	{
		console.log ('аналогично');
	});
	
	// ...
});

// ...
  • Вопрос задан
  • 4890 просмотров
Подписаться 2 Средний Комментировать
Решения вопроса 1
@Abcdefgk
Короче, я тут поковырялся. И у меня получилось за Нгинксом его заставить работать, но только - создавая "пространство имён" принудительно.
На клиенте запрос на подключение выглядит так
var socket = io('http://localhost/sock');
на сервере так
var io = require('socket.io')(3001); // спицально ему другой порт прикрутил, для "чистоты эксперимента"
var chat = io.of('/sock');
chat.on('connection', socket => { ...

и дальше везде, где был io в коде - заменить на переменную chat - типа chat.to(socket.id).emit... и т.д. (хотя, видимо, можно было и просто - io переопределить: io = io.of('/sock');).
И наконец, Nginx его перенаправляет так
location /sock {
						proxy_set_header Upgrade $http_upgrade;
						proxy_set_header Connection "upgrade";
						proxy_http_version 1.1;
						proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
						proxy_set_header Host $host;
						proxy_pass http://127.0.0.1:3001/sock;
				}

Так всё зафурычило.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Kizilov
@Kizilov
Front-end developer
Я не уверен, но у тебя стоит location /ws. Попробуй /socket.io
Почему не работает socket.io на nginx?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы