Вопрос: Nginx удаляет заголовок Content-Length для фрагментированного контента


Я использую nginx 1.2.3 для прокси-сервера для скрипта:

proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8880;
proxy_buffering off;
proxy_read_timeout 300s;
gzip off;

Сценарии отправляют оба Transfer-encoding: chunked а также Content-Length: 251:

HTTP/1.0 307 Temporary Redirect
Content-length: 251
Pragma: no-cache
Location: /...
Cache-control: no-cache
Transfer-encoding: chunked

Мне нужно обоим, но nginx автоматически удаляет Content-Length:

HTTP/1.1 302 Found
Server: nginx/1.2.3
Content-Type: application/json; charset=utf-8
Content-Length: 58
Connection: keep-alive
Location: /...

В результате клиенты не ждут отправки кусков. Это использовалось для работы с более ранней версией nginx.


10
2018-02-27 04:48


Источник


Как выглядят заголовки из прокси-сервера nginx? - hrunting
с какой версией он работал? - cnst
Он работал с nginx 0.9.8 - Julien
Вы нарушаете протокол HTTP. Он работает с nginx 0.9.8, потому что до версии 1.1.4 он вообще не поддерживает кодирование с кодировкой. - VBart


Ответы:


К сожалению, я не могу комментировать пост cnst, поэтому я собираюсь ответить здесь.

nginx_http_proxy модуль по умолчанию разговаривает с восходящим потоком в HTTP / 1.0. Это можно изменить с помощью директивы proxy_http_version 1.1,

Это может также послужить причиной того, что ваш скрипт вернет ответ HTTP / 1.0, хотя код кодирования и статуса 307 не существует в этой версии.

Вы не должны использовать закодированное кодирование с помощью переадресовывать либо, поскольку это не имеет смысла.

Дополнительно, это похоже на nginx не пропускает куски от восходящего потока к клиенту один за другим, но это буферизирует ответ восходящего потока, Content-Length поле заголовка игнорируется, поскольку оно противоречит определению. Мне пришлось смотреть на исходный код модуля, потому что все это, как представляется, недокументировано.

Вы можете попробовать nginx_tcp_proxy_module для проксирования помеченного содержимого как необработанных данных TCP: Модуль в Github


ОБНОВИТЬ (10.04.14)
nginx_http_proxy модуль поддерживает X-Accel-*  заголовки, из которых один (X-Accel-Buffering: yes|no) контролирует, должен ли буфер быть буферизирован или нет.

Добавление этого заголовка (X-Accel-Buffering: no) на ответ бэкэнда заставит nginx напрямую передавать куски клиенту.

Этот заголовок позволяет управлять буферизацией на по запросу,

Модуль также имеет директива конфигурации  proxy_buffering для включения или отключения буферизации ответа (не буферизация означает, что будут выполняться куски отправки).

Буферизация прокси (как заголовка, так и директивы) документирована Вот,


9
2018-03-10 15:59



Он не должен этого делать даже с nginx_tcp_proxy_module, Он работает с некоторыми браузерами только потому, что они очень устойчивы к ошибкам. - VBart
потому что все это, как представляется, недокументировано Неправильно. Это описано в RFC 2616. См. 13.5.1, - VBart
@VBart Конечно, есть стандарты, но есть только очень немного информации о том, насколько далеко Nginx реализует их. Модуль прокси-сервера TCP обходной путь, - Lukas


Как указывает Лукас, HTTP 1.1 запрещает Content-Length если есть Transfer-Encoding задавать.

квотирование http://www.ietf.org/rfc/rfc2616.txt:

   3.If a Content-Length header field (section 14.13) is present, its
     decimal value in OCTETs represents both the entity-length and the
     transfer-length. The Content-Length header field MUST NOT be sent
     if these two lengths are different (i.e., if a Transfer-Encoding
     header field is present). If a message is received with both a
     Transfer-Encoding header field and a Content-Length header field,
     the latter MUST be ignored.

8
2017-09-29 22:14





Вы не уточнили, почему ваш сценарий нуждается в кодировке с кодировкой в ​​первую очередь, особенно с ответом на перенаправление.

Здесь я вижу множество проблем.

  • Transfer-Encoding: chunked является HTTP/1.1 (и ваш скрипт, кажется, отвечает HTTP/1.0 заголовок)

  • здесь нет 307 в HTTP/1.0

  • вся цель chunked заключается в том, что вы не знаете, что Content-Length было бы так, chunked используется вместо обеспечения длины в пределах Content-Length, где вместо этого в теле ответа содержатся длины, смешанные с фактическим содержимым; было бы бессмысленно, чтобы скрипт генерировал оба заголовка заранее

Я лично не знаком с chunked, но согласно основной информации в http://en.wikipedia.org/wiki/Chunked_transfer_encoding а также http://tools.ietf.org/html/rfc2616#section-3.6.1, Я бы предположил, что полная обработка вашего скрипта с кодировкой может быть совершенно неправильной.

Если вышеупомянутое все еще не охватывает его, и во всей действительности в противном случае, также неясно, почему ответ с 307 или 302 Код статуса http должен быть снабжен «странным» кодированием. Недавно была аналогичная дискуссия в списке рассылки nginx о 410 Gone и другие страницы ошибок всегда исключаются из gzip сжатие, и я думаю, что в равной степени это будет иметь место. (http://mailman.nginx.org/pipermail/nginx/2013-March/037890.html)


3
2018-03-05 21:07



Я использую его, чтобы пользователь подождал: я посылаю куски каждую секунду, так что пользователь будет ждать перенаправления в течение X секунд, не получая тайм-аут - Julien
Я бы посоветовал сначала исправить HTTP / 1.0 до HTTP / 1.1 (эти вещи делать сделайте разницу), и убедитесь, что ваша закодированная кодировка не является неправильной. Более новая версия nginx, вероятно, отбрасывает некоторые заголовки, от которых вы зависите, потому что они ошибаются. - cnst


У меня была такая же проблема, как поток mp4-файла с помощью тега html5.

Safari и Firefox ведут себя нормально, тогда как Chrome в какой-то момент запускает ERR_CONTENT_LENGTH_MISMATCH (но это позволило мне проследить несколько минут видео до сбоя).

Проблема не была воспроизведена после того, как я отключил управление кешем для файлов mp4.


1
2017-09-10 05:30