Socket.io не отключается через Cloudflare / Nginx - PullRequest
0 голосов
/ 24 марта 2019

У меня есть небольшое веб-приложение, которое поставляется с Express.js и подключается к бэкэнду с Socket.io. Чтобы сделать его публичным, я использую Nginx в качестве обратного прокси-сервера, а затем Cloudflare в самом начале. Приложение опирается на событие disconnect, когда оно закрывается или перезагружается, чтобы отслеживать, помимо прочего, онлайн-пользователей. При прохождении через Nginx и Cloudflare событие отключения никогда не запускается на бэкэнде. Это происходит при локальном развитии.

Вот мой конфигурационный файл Nginx:

server {
    listen 80;
    server_name colab.gq;
    server_name www.colab.gq;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header X-Forwarded-For $remote_addr;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/colab.gq/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/colab.gq/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

А вот фрагмент моего серверного кода:

io.on('connection', (socket) => {
  // Stuff here

  socket.on('disconnect', () => {
    console.log('disconnected!')
    // Stuff that relies on the disconnect event
  })
})

Когда пользователь закрывает вкладку или перезагружает страницу, событие отключения должно сработать, но оно никогда не происходит при прохождении соединения через Nginx и Cloudflare. Заранее спасибо за любую помощь!

ОБНОВЛЕНИЕ: Кажется, что через несколько секунд после перезагрузки / закрытия событие отключения наконец регистрируется.

Ответы [ 2 ]

1 голос
/ 27 марта 2019

То, что, вероятно, происходит, это 2 вещи.

1-й: Socket.io имеет длительный тайм-аут (отсюда несколько секунд) и пытается восстановить соединение, прежде чем объявить, что он был отключен.Проверьте событие reconnect_attempt или restnecting (обратите внимание, что я некоторое время не использовал socket.io, поэтому я могу ошибиться в выборе времени для этого)

2-й: вы не говорите socket.io, что он отключаетсяпосле закрытия окна браузера.

Я бы порекомендовал добавить слушатель событий в ваш javascript, который сообщит вашему серверу, что он отключается при закрытии окна.

    window.addEventListener('beforeunload', () => {
       socket.disconnect();
    }
1 голос
/ 27 марта 2019

Вы должны добавить заголовки обновления к вашему сокету io path в конфигурации nginx следующим образом:

    location ~* \.io {
      .. your configuration

      proxy_pass http://localhost:3000;
      proxy_redirect off;

      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
    }

Поскольку вы запросили расширение ответа, первое, что вы, возможно, уже знаетеis socket.io - это протокол, который использует протокол Websockets под капотом (поэтому оба они одинаковы).В качестве стандартов и протоколы Websockets, и протоколы HTTP прослушивают один и тот же порт 80 или 443. Протокол по умолчанию - HTTP, если пользователь хочет использовать протокол websockets, он / она должен отправить запрос на обновление с HTTP на протокол WS, и есть какой-то ключаутентификация и шаги.

Вот почему вам нужно поместить их в конфигурацию nginx.

Если вам нужна дополнительная информация о механизме обновления протокола, обратитесь к этому .

Хотя, на мой взгляд, это не точный дубликат этого вопроса, я чувствую себя обязанным дать кредиты для @ Paulo за предоставление идеального ответа, хотя и не принят.

...