Вопрос или проблема
У меня есть бэкэнд, который устанавливает заголовок Cookie после входа в систему для refresh-token. Теперь на моем фронтэнде (next.js, pages router) я устанавливаю это в отклике того клиента для серверных API вызовов, чтобы клиент мог делать API вызовы независимо, а также гидратировать его на стороне сервера для SSR.
try {
const clientIp = requestIp.getClientIp(req);
const { data, headers: returnedHeaders } = await postLogin(undefined, clientIp, 'api/auth/authenticate-anonymous');
Object.entries(returnedHeaders).forEach(keyArr => {
res.setHeader(keyArr[0], keyArr[1]);
})
res.setHeader('Transfer-Encoding', '');
return res.send(data);
} catch (err) {
return res.send(err);
}
Все это работает локально, даже я настроил nginx на своем ПК, и это работает, но на AWS API дают ошибку 502 с журналами: upstream sent unknown “Transfer-Encoding”: “” while reading response header from upstream. Если я не удаляю Transfer-encoding, то получаю эту ошибку: upstream sent “Content-Length” and “Transfer-Encoding” headers at the same time while reading response header from upstream.
Вот мой nginx.conf:
# Конфигурационный файл Nginx для Elastic Beanstalk
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 200000;
events {
worker_connections 1024;
}
http {
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
server {
listen 80 default_server;
access_log /var/log/nginx/access.log main;
client_header_timeout 60;
client_body_timeout 60;
keepalive_timeout 60;
gzip on;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# Включить сгенерированные Elastic Beanstalk локации
# include conf.d/elasticbeanstalk/*.conf;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
# Правильные заголовки прокси
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Убедитесь, что буферизация включена
proxy_buffering on;
proxy_buffers 16 16k;
proxy_buffer_size 16k;
# Удалить пустые заголовки Transfer-Encoding из upstream
proxy_hide_header Transfer-Encoding;
# proxy_set_header Connection $connection_upgrade;
proxy_set_header Connection "";
# proxy_set_header Upgrade $http_upgrade;
}
}
}
Ответ или решение
Проблема, описанная вами, связана с особенностями работы заголовков HTTP и их обработкой в Nginx при проксировании запросов. Ошибка upstream sent unknown "Transfer-Encoding": "" while reading response header from upstream
указывает на то, что Nginx не ожидает пустого заголовка Transfer-Encoding
от вашего бэкенда. Аналогично, ошибка upstream sent "Content-Length" and "Transfer-Encoding" headers at the same time while reading response header from upstream
возникает, когда одновременно используются заголовки Content-Length
и Transfer-Encoding
, что конфликтует.
Основные причины и решения проблемы
-
Необходимость заголовка Transfer-Encoding:
ЗаголовокTransfer-Encoding
используется для указания способа передачи данных. Если ваш бэкенд явно устанавливаетTransfer-Encoding
, он должен делать это корректно. Убедитесь, что ваш бэкенд отправляет только один из заголовков: либоContent-Length
, либоTransfer-Encoding
. -
Настройка заголовков в коде:
В вашем коде вы устанавливаетеTransfer-Encoding
пустым значением. Это может приводить к конфликтам. Вместо этого не устанавливайте этот заголовок вообще, если хотите, чтобы Nginx сам справился с определением кодировки передачи:// Уберите эту строку // res.setHeader('Transfer-Encoding', '');
Кроме того, если ваш бэкенд возвращает данные с заголовком
Content-Length
, убедитесь, чтоTransfer-Encoding
не добавляется. -
Конфигурация Nginx:
В вашей конфигурации Nginx вы правильно сконфигурировали проксирование. Добавлениеproxy_hide_header Transfer-Encoding;
помогает удалить заголовокTransfer-Encoding
, отправляемый вашим приложением, до того, как Nginx его обработает. -
Проверка ответов от сервера:
Для получения корректных заголовков убедитесь, что ваш бэкенд возвращает правильные значения. Проверьте, как ваш сервер обрабатывает заголовкиContent-Length
иTransfer-Encoding
. Если ваш сервер возвращает данные без использованияTransfer-Encoding
, то не должно быть конфликта сContent-Length
. -
Логирование:
Проверьте логи вашего приложения на наличие дополнительных подсказок о том, какие заголовки возвращаются вашим бэкендом. Логи Nginx также могут помочь выявить проблему.
Рекомендации
- Убедитесь, что API, которые вы вызываете, не добавляют ненужные заголовки
Transfer-Encoding
. - Возможно, стоит рассмотреть использование регулярных выражений или middleware для фильтрации заголовков, если у вас есть бэкенд-подсистемы, которые могут добавлять их без необходимости.
- Тестируйте изменения на локальном окружении, используя настройки, аналогичные вашим продакшен-средам.
- Если ошибка продолжает появляться, облачная среда AWS может внести специфические особенности в работу вашего приложения, так что подумайте о создании окружения, аналогичного продакшену, для более тщательного тестирования.
Надеюсь, эти рекомендации помогут вам решить возникшие проблемы с вашими API и Nginx на AWS.