upstream отправил неизвестный “Transfer-Encoding”: “” при чтении заголовка ответа от upstream

Вопрос или проблема

У меня есть бэкэнд, который устанавливает заголовок 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, что конфликтует.

Основные причины и решения проблемы

  1. Необходимость заголовка Transfer-Encoding:
    Заголовок Transfer-Encoding используется для указания способа передачи данных. Если ваш бэкенд явно устанавливает Transfer-Encoding, он должен делать это корректно. Убедитесь, что ваш бэкенд отправляет только один из заголовков: либо Content-Length, либо Transfer-Encoding.

  2. Настройка заголовков в коде:
    В вашем коде вы устанавливаете Transfer-Encoding пустым значением. Это может приводить к конфликтам. Вместо этого не устанавливайте этот заголовок вообще, если хотите, чтобы Nginx сам справился с определением кодировки передачи:

    // Уберите эту строку
    // res.setHeader('Transfer-Encoding', '');

    Кроме того, если ваш бэкенд возвращает данные с заголовком Content-Length, убедитесь, что Transfer-Encoding не добавляется.

  3. Конфигурация Nginx:
    В вашей конфигурации Nginx вы правильно сконфигурировали проксирование. Добавление proxy_hide_header Transfer-Encoding; помогает удалить заголовок Transfer-Encoding, отправляемый вашим приложением, до того, как Nginx его обработает.

  4. Проверка ответов от сервера:
    Для получения корректных заголовков убедитесь, что ваш бэкенд возвращает правильные значения. Проверьте, как ваш сервер обрабатывает заголовки Content-Length и Transfer-Encoding. Если ваш сервер возвращает данные без использования Transfer-Encoding, то не должно быть конфликта с Content-Length.

  5. Логирование:
    Проверьте логи вашего приложения на наличие дополнительных подсказок о том, какие заголовки возвращаются вашим бэкендом. Логи Nginx также могут помочь выявить проблему.

Рекомендации

  • Убедитесь, что API, которые вы вызываете, не добавляют ненужные заголовки Transfer-Encoding.
  • Возможно, стоит рассмотреть использование регулярных выражений или middleware для фильтрации заголовков, если у вас есть бэкенд-подсистемы, которые могут добавлять их без необходимости.
  • Тестируйте изменения на локальном окружении, используя настройки, аналогичные вашим продакшен-средам.
  • Если ошибка продолжает появляться, облачная среда AWS может внести специфические особенности в работу вашего приложения, так что подумайте о создании окружения, аналогичного продакшену, для более тщательного тестирования.

Надеюсь, эти рекомендации помогут вам решить возникшие проблемы с вашими API и Nginx на AWS.

Оцените материал
Добавить комментарий

Капча загружается...