Nginx remove o cabeçalho Content-Length do conteúdo em pedaços

10

Eu uso o nginx 1.2.3 como proxy para um script:

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

Os scripts enviam Transfer-encoding: chunked e Content-Length: 251 :

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

Eu preciso dos dois, mas o nginx remove automaticamente o 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: /...

Como resultado, os clientes não esperam que os fragmentos sejam enviados. Isso costumava funcionar com uma versão anterior do nginx.

    
por Julien 27.02.2013 / 05:48

4 respostas

9

Infelizmente, não posso comentar o post do cnst - por isso vou responder aqui.

O módulo nginx_http_proxy por padrão fala com o upstream no HTTP / 1.0. Isso pode ser alterado com a diretiva proxy_http_version 1.1 .

Isso também pode ser a causa do seu script retornar uma resposta HTTP / 1.0, embora a codificação em partes e o código de status 307 não existam nesta versão.

Você não deve usar codificação em partes com um redirecionamento , pois isso não faz sentido.

Além disso , parece que o nginx não passa pedaços do upstream ao cliente um por um, mas buffers a resposta do upstream . O campo de cabeçalho Content-Length é ignorado porque é contra a definição. Eu tive que olhar para o código fonte do módulo porque tudo isso parece estar indocumentado.

Você pode experimentar o nginx_tcp_proxy_module para representar o conteúdo em partes como dados brutos do TCP: Módulo no Github

UPDATE (10.04.14)
O módulo nginx_http_proxy tem suporte para X-Accel-* cabeçalhos , dos quais um ( X-Accel-Buffering: yes|no ) controla se a resposta deve ser armazenada em buffer ou não.

Adicionar este cabeçalho ( X-Accel-Buffering: no ) à resposta do backend fará com que o nginx passe diretamente pedaços para o cliente.

Esse cabeçalho permite controlar o buffer em uma base por solicitação .

O módulo também tem uma diretiva de configuração proxy_buffering para habilitar ou desabilitar o buffer de resposta (não armazenar em buffer significa que o envio de partes funcionará).

O armazenamento em buffer proxy (com base no cabeçalho e na diretiva) está documentado aqui .

    
por 10.03.2013 / 16:59
8

Como Lukas alludet para, o HTTP 1.1 proíbe Content-Length se houver um Transfer-Encoding definido.

Citando o link :

   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.
    
por 30.09.2013 / 00:14
3

Você não elaborou especificamente por que seu script precisa de codificação fragmentada, em especial com uma resposta de redirecionamento.

Eu vejo uma infinidade de problemas aqui.

  • Transfer-Encoding: chunked é um recurso HTTP/1.1 (e seu script parece estar respondendo com um cabeçalho HTTP/1.0 )

  • não há 307 em HTTP/1.0

  • o objetivo completo de chunked é que você não sabe qual teria sido o seu Content-Length , portanto, chunked é usado no lugar de fornecer o comprimento em Content-Length , em vez disso, comprimentos são fornecidos dentro do corpo da resposta, misturados com o conteúdo real; seria inútil que um script gerasse os dois cabeçalhos antecipadamente

Não estou pessoalmente familiarizado com chunked , mas de acordo com as informações básicas no link e também link , eu suponho que a manipulação total do script da codificação em partes pode estar completamente errada.

Se o item acima ainda não o cobre, e em toda a realidade, também não está claro por que uma resposta com um código de status 307 ou 302 http deve ser fornecida com uma codificação "estranha". Recentemente houve uma discussão semelhante na lista de discussão nginx sobre 410 Gone e outras páginas de erro sempre excluídas da compactação gzip , e acho que o sentimento se aplicaria igualmente aqui. ( link )

    
por 05.03.2013 / 22:07
1

Eu tive o mesmo problema ao transmitir o arquivo mp4 por meio da tag de vídeo html5.

O Safari e o Firefox se comportaram normalmente, enquanto o Chrome estava acionando ERR_CONTENT_LENGTH_MISMATCH em algum momento (mas permitiu que eu anotasse vários minutos do vídeo antes de falhar).

O problema não se reproduziu depois que eu desliguei o controle de cache para arquivos mp4.

    
por 10.09.2014 / 07:30

Tags