nginx upload client_max_body_size issue


117

Estou executando o nginx / ruby-on-rails e tenho um formulário simples de várias partes para fazer upload de arquivos. Tudo funciona bem até eu decidir restringir o tamanho máximo dos arquivos que desejo enviar. Para fazer isso, defino o nginx client_max_body_sizepara 1m (1 MB) e espero um status HTTP 413 (Solicitar Entidade Muito Grande) em resposta quando a regra é quebrada.

O problema é que quando eu carrego um arquivo de 1,2 MB, em vez de exibir a página de erro HTTP 413, o navegador trava um pouco e morre com a mensagem "A conexão foi reiniciada enquanto a página carregava".

Eu tentei quase todas as opções que o nginx oferece, mas nada parece funcionar. Alguém tem alguma ideia sobre isso?

Aqui está meu nginx.conf:

worker_processes  1;
timer_resolution  1000ms;
events {
    worker_connections  1024;
}

http {
    passenger_root /the_passenger_root;
    passenger_ruby /the_ruby;

    include       mime.types;
    default_type  application/octet-stream;

    sendfile           on;
    keepalive_timeout  65;

    server {
      listen 80;
      server_name www.x.com;
      client_max_body_size 1M;
      passenger_use_global_queue on;
      root /the_root;
      passenger_enabled on;

      error_page 404 /404.html;
      error_page 413 /413.html;    
    }    
}

Obrigado.


**Edit**

Ambiente / UA: Windows XP / Firefox 3.6.13

Respostas:


128

nginx "falha rápido" quando o cliente informa que vai enviar um corpo maior que o client_max_body_sizeenviando uma resposta 413 e fechando a conexão.

A maioria dos clientes não lê as respostas até que todo o corpo da solicitação seja enviado. Como o nginx fecha a conexão, o cliente envia dados para o soquete fechado, causando um TCP RST.

Se o seu cliente HTTP suportar, a melhor maneira de lidar com isso é enviar um Expect: 100-Continuecabeçalho. O Nginx suporta isso corretamente a partir de 1.2.7 e responderá com uma 413 Request Entity Too Largeresposta em vez de 100 Continuese Content-Lengthexceder o tamanho máximo do corpo.


1
Oh, devo salientar que esta resposta pressupõe que o cliente está enviando, Content-Lengthe não fazendo Transfer-Encoding: chunked.
Joe Shaw

2
O autor do nginx postou um patch para corrigir isso na lista de discussão: nginx.2469901.n2.nabble.com/… No entanto, nenhuma palavra se será adicionado ao branch estável 1.2.x.
Joe Shaw

Obrigado, isso na verdade explica muita coisa. Certamente parece Expectser o caminho a seguir para grandes solicitações.
Krukid de

Atualizei minha resposta para observar que o patch que mencionei anteriormente foi confirmado e incorporado à versão 1.2.7.
Joe Shaw

Só para economizar tempo procurando uma sintaxe legal (como eu passei): request.setHeader(HttpHeaders.EXPECT, CONTINUE);com import org.apache.http.HttpHeaders;eimport static org.jboss.netty.handler.codec.http.HttpHeaders.Values.CONTINUE;
Erez Cohen

48

Seu upload morre bem no final? 99% antes de cair? O corpo e os buffers do cliente são essenciais porque o nginx deve armazenar os dados de entrada. As configurações do corpo (dados do corpo da solicitação) especificam como o nginx lida com o fluxo em massa de dados binários de clientes de formulários com várias partes para a lógica do seu aplicativo.

A cleanconfiguração libera memória e limites de consumo instruindo o nginx a armazenar o buffer de entrada em um arquivo e, em seguida, limpar esse arquivo mais tarde do disco, excluindo-o.

Definir body_in_file_onlya cleane ajustar buffers para a client_max_body_size. A configuração da pergunta original já tinha o sendfile ativado, aumente o tempo limite também. Eu uso as configurações abaixo para corrigir isso, apropriadas em seus contextos de configuração local, servidor e http.

client_body_in_file_only clean;
client_body_buffer_size 32K;

client_max_body_size 300M;

sendfile on;
send_timeout 300s;

Mesmo que isso resulte no nginx retornando um HTTP 413 adequado, o UA ainda enviará todo o corpo da solicitação, não é? Nesse caso, acho que vale a pena tentar a abordagem sugerida por @joe-shaw.
Krukid

@krukid quando parece que temos 99% de upload concluído antes do NGINX "falhar rapidamente", concordo com você. Nesse caso, todos os sinais são positivos em torno do objeto de solicitação, ou seja, o diagnóstico indica que a lógica do aplicativo do servidor interno está correta - tudo o que for executado por trás do Nginx. Portanto, embora seja provável que a solicitação tenha sido bem formulada, nossa necessidade é considerar por que o NGINX engasga com a resposta. client_max_body_size deve ser a primeira opção de configuração que verificamos, então considere os buffers, porque com um upload grande o suficiente, a solução correta depende de quanta memória nosso servidor pode controlar também.
Bent Cardan

@Bent Cardan. Essa abordagem parecia ser a melhor e eu tentei. Mas ainda estou recebendo um erro 413 após cerca de 20 segundos para um arquivo de 4 MB. Minhas velocidades de aumento não conseguem gerenciar 4 MB em 20 segundos, então isso está acontecendo depois que os dados fluem por um bom tempo. Pensamentos?
Jerome

Eu adicionei as alterações no arquivo nginx.conf _client_max_body_size 300M; sendfile ativado; send_timeout 300s; _ Está funcionando perfeitamente para mim Obrigado
Ramesh Chand

A solução funciona para mim em openshift php7 nginx.
marlo

7

Da documentação :

É necessário ter em mente que os navegadores não sabem mostrar corretamente este erro.

Suspeito que seja isso o que está acontecendo, se você inspecionar o HTTP para frente e para trás usando ferramentas como Firebug ou Live HTTP Headers (ambas extensões do Firefox), você poderá ver o que realmente está acontecendo.


1
Também descobri isso aqui: forum.nginx.org/read.php?2,2620 Onde o autor do nginx diz que as pessoas poderiam tentar alterar lingering_time / lingering_timeout - ambos os quais não tiveram efeito no meu caso. Além disso, eu simplesmente não vejo como pode haver um problema de tempo limite persistente quando estou carregando um arquivo de 1,2 MB com um limite de 1 MB facilmente com uma conexão estável de 5 Mbps. Eu cheirei a resposta e ele enviará a página 413 com o cabeçalho "Conexão: fechar", mas a conexão não parece fechar.
Krukid

Acho que é difícil acreditar que, embora haja um status HTTP 413 perfeitamente válido, ele não é acionado nos navegadores. Pesquisei vários lugares onde as pessoas não conseguem se livrar dessa página e nunca a vi.
Krukid de

Se você desativar o passageiro, a conexão será fechada?
Mark Rose

Bem, comparei as respostas com e sem passageiro. Quando tudo funciona normalmente e eu carrego um arquivo várias vezes maior (~ 14 MB) do que minha restrição de 1 MB, recebo 413 respostas várias vezes (porque o cliente continua enviando pedaços) e a "reconfiguração de conexão" final parece um tempo limite. Sem o passageiro, recebo uma resposta instantânea 413 e todo o progresso é interrompido, mas ainda vejo a página "Redefinição da conexão", não meu 413.html estático ou qualquer coisa que implique "Entidade muito grande"
krukid
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.