Траблшутинг ошибок WebSocket в Nginx: заголовки Upgrade и Connection
- Ошибка в консоли браузера:
WebSocket connection to 'wss://example.com/ws' failed: Error during WebSocket handshake: Unexpected response code: 400(или 502). - Соединение WebSocket обрывается ровно через 60 секунд после установления сессии.
- Nginx пересылает HTTP/1.0 вместо HTTP/1.1 при проксировании постоянных WebSocket сокетов.
1. Настройка динамического маппинга заголовков в nginx.conf
Добавьте блок map внутри контекста http (в /etc/nginx/nginx.conf):
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}2. Конфигурация проксирования WebSocket в блоке location
В файле виртуального хоста сконфигурируйте эндпоинт:
location /ws/ {
proxy_pass http://backend_websocket_upstream;
# Обязательно HTTP/1.1 для протокола Upgrade
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# Проброс заголовков хоста и реального IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Увеличение таймаута неактивности (по умолчанию 60с)
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}3. Проверка синтаксиса и перезагрузка
nginx -t && systemctl reload nginx4. Тестирование с помощью wscat
npm install -g wscat
wscat -c wss://example.com/ws/ Частые вопросы (FAQ)
Почему WebSocket соединение разрывается каждые 60 секунд?
Если через сокет не передаются данные (heartbeat/ping-pong), срабатывает стандартный тайм-аут proxy_read_timeout (60 сек). Для исправления увеличьте proxy_read_timeout до суток (86400s) или настройте WebSocket Ping на клиенте/сервере.
Зачем использовать конструкцию map вместо жесткого proxy_set_header Connection 'upgrade'?
Жесткое указание 'upgrade' ломает стандартные HTTP-запросы (REST API), проходящие через этот же location. Конструкция map отправляет заголовок 'upgrade' только тогда, когда клиент явно запросил $http_upgrade, в противном случае отправляя 'close'.