Nginx: upstream sent invalid header: chunked — Решение ошибки 502
При обращении к бэкенд-серверу через реверс-прокси Nginx соединение завершается со статусом 502 Bad Gateway. В системном журнале error.log регистрируется ошибка разбора HTTP-заголовков: upstream sent invalid header: "chunked" while reading response header from upstream или invalid Transfer-Encoding header.
| Симптом | Уровень сбоя | Техническая причина |
|---|---|---|
| Ошибка 502 Bad Gateway | HTTP/1.1 Transport Layer | Бэкенд возвращает некорректно отформатированный заголовок Transfer-Encoding: chunked |
| Проксирование HTTP/1.0 | Nginx Core Upstream | Nginx по умолчанию опрашивает бэкенд по HTTP/1.0, где chunked-encoding запрещен |
| Сдвоенный Transfer-Encoding | Бэкенд-фреймворк (Node, Go, Python) | Заголовок дублируется или содержит синтаксический мусор (CRLF injection / raw bytes) |
- Клиентский запрос не может быть завершен, браузер получает пустой или аварийный ответ 502.
- Прямой запрос к бэкенду через
curl -iвозвращает нестандартные или дублирующиеся заголовкиTransfer-EncodingиContent-Lengthодновременно.
- Переключите протокол взаимодействия Nginx с upstream на HTTP/1.1 и сбросьте заголовок соединения в соответствующем блоке
locationилиupstream:location / { proxy_pass http://backend_upstream; proxy_http_version 1.1; proxy_set_header Connection ""; } - Устраните коллизии одновременной отправки
Content-LengthиTransfer-Encodingна стороне бэкенда. Согласно спецификации RFC 7230, наличие обоих заголовков одновременно недопустимо. - Если бэкенд формирует нестандартные HTTP-заголовки, включите временный пропуск некорректных заголовков (если допустимо логикой приложения):
ignore_invalid_headers on; - Если upstream передает сырой HTTP-ответ с кастомного сокета или скрипта, проверьте окончания строк заголовков — они должны содержать строго последовательность
\r\n(CRLF), а не одиночный\n. - Проверьте синтаксис конфигурации Nginx и примените настройки:
sudo nginx -t sudo systemctl reload nginx
ngx_http_proxy_module использует протокол HTTP/1.0 для связи с бэкендами. Указание proxy_http_version 1.1; является обязательным для всех современных асинхронных бэкендов на Node.js, Go, Python (ASGI) и Netty.Частые вопросы (FAQ)
Почему Nginx по умолчанию использует HTTP/1.0 к upstream?
Исторически HTTP/1.0 был выбран для упрощения буферизации ответов и управления соединениями. Для поддержки persistent connections и chunked streaming требуется явное указание proxy_http_version 1.1;.
Чем опасна одновременная отправка Content-Length и Transfer-Encoding?
Такая комбинация создает уязвимость HTTP Request Smuggling / Desync Attack, так как промежуточные прокси-серверы и бэкенд могут по-разному определять границы запроса.
Как увидеть сырые заголовки от бэкенда напрямую?
Выполните прямой запрос к порту сервиса: curl -v -N --raw http://127.0.0.1:8080/path.
Поможет ли включение chunked_transfer_encoding on?
Директива chunked_transfer_encoding управляет отправкой данных от Nginx к клиенту, но не исправляет поврежденные заголовки, приходящие от upstream к самому Nginx.