2011-02-09 2 views
99

Sto eseguendo nginx/ruby-on-rail e ho un semplice modulo multipart per caricare i file. Tutto funziona correttamente finché non decido di limitare la dimensione massima dei file che voglio caricare. Per fare ciò, imposto il nginx a 1m (1MB) e ci si aspetta uno stato HTTP 413 (Richiedi Entità troppo grande) in risposta quando tale regola si interrompe.nginx upload client_max_body_size issue

Il problema è che quando aggiungo un file 1.2 MB, invece di visualizzare la pagina di errore HTTP 413, il browser si blocca un po 'e poi muore con un "collegamento è stato ripristinato mentre la pagina stava caricando" il messaggio.

Ho provato praticamente ogni opzione che offre Nginx, niente sembra funzionare. Qualcuno ha qualche idea su questo?

Ecco la mia 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;  
    }  
} 

Grazie.


**Edit**

Ambiente/UA: Windows XP/Firefox 3.6.13

risposta

109

nginx "fallisce veloce" quando il client lo informa che sta per inviare un corpo più grande del client_max_body_size inviando una risposta 413 e chiudendo la connessione.

La maggior parte dei client non legge le risposte finché non viene inviato l'intero corpo della richiesta. Poiché nginx chiude la connessione, il client invia i dati al socket chiuso, causando un RST TCP.

Se il client HTTP lo supporta, il modo migliore per gestirlo è inviare un'intestazione Expect: 100-Continue. Nginx supporta questo correttamente come da 1.2.7 e risponderà con una risposta 413 Request Entity Too Large anziché 100 Continue se Content-Length supera la dimensione massima del corpo.

+1

Oh, vorrei sottolineare che questa risposta presuppone che il client sta inviando 'Content-Length' piuttosto che' Transfer-Encoding: chunked'. –

+2

L'autore di nginx ha pubblicato una patch per risolvere questo problema sulla mailing list: http://nginx.2469901.n2.nabble.com/client-max-body-size-and-100-Continue-413-Request-Entity-Too -Large-tp7582547p7582554.html Nessuna parola, tuttavia, se verrà aggiunta al ramo stabile 1.2.x. –

+0

Grazie, questo in realtà spiega molto. Certamente sembra che "Aspettatevi" sia la strada da percorrere per richieste di grandi dimensioni. – krukid

7

Da the documentation:

È necessario tenere a mente che i browser fanno non so come mostrare correttamente questo errore.

ho il sospetto che questo è ciò che sta succedendo, se si ispezionare il HTTP a va e vieni utilizzando strumenti come Firebug o Live HTTP Headers (entrambe le estensioni di Firefox) sarete in grado di vedere ciò che sta realmente accadendo.

+1

ho incontrato che anche qui: http://forum.nginx.org/read.php?2,2620 dove l'autore nginx dice la gente potrebbe provare a cambiare lingering_time/lingering_timeout - entrambi i quali avevano nessun effetto nel mio caso. Inoltre, non vedo come potrebbe esserci un problema di timeout persistente quando sto caricando un file da 1.2MB con un limite di 1MB facilmente avendo una connessione fissa a 5Mbps. Ho annusato la risposta e invia la pagina 413 con l'intestazione "Connection: close", ma la connessione sembra non chiudersi. – krukid

+0

Immagino di avere difficoltà a credere che anche se esiste uno stato HTTP 413 perfettamente valido, non si attiva nei browser. Ho cercato su Google un sacco di posti in cui le persone non possono sbarazzarsi di quella pagina e non l'ho mai nemmeno visto. – krukid

+0

Se disabiliti il ​​passeggero, chiude la connessione? –

41

Il tuo caricamento muore alla fine? 99% prima di schiantarsi? Il corpo del client e i buffer sono fondamentali perché nginx deve bufferizzare i dati in entrata. Le configurazioni del corpo (dati del corpo della richiesta) specificano come nginx gestisce il flusso di massa di dati binari da client in più parti nella logica della tua app.

L'impostazione clean libera limiti di memoria e consumo istruendo nginx per memorizzare il buffer in arrivo in un file e quindi pulisce questo file in seguito dal disco eliminandolo.

Impostare body_in_file_only-clean e regolare buffer per il client_max_body_size.La configurazione della domanda originale aveva già sendfile on, aumenta anche i timeout. Io uso le impostazioni di seguito per risolvere questo problema, appropriato attraverso il tuo locale config, server, contesti http & http.

client_body_in_file_only clean; 
client_body_buffer_size 32K; 

client_max_body_size 300M; 

sendfile on; 
send_timeout 300s; 
+0

Anche se questo fa sì che nginx restituisca un HTTP 413 corretto, UA continuerà comunque a inviare l'interezza del corpo della richiesta, non sarà così? In tal caso, penso che valga la pena provare l'approccio suggerito da @ joe-shaw. – krukid

+0

@krukid quando sembra che abbiamo ottenuto il 99% di upload completo prima che NGINX "fallisca velocemente", sono d'accordo con te. In questo caso, tutti i segni sono positivi attorno all'oggetto della richiesta, cioè la diagnosi è che la logica dell'applicazione del server interno va bene - qualsiasi cosa avvenga dietro Nginx. Quindi, mentre è probabile che la richiesta sia stata ben formata, il nostro bisogno è quindi di considerare perché NGINX soffoca sulla risposta. client_max_body_size dovrebbe essere la prima opzione di configurazione che consideriamo, quindi considerare i buffer, perché con un caricamento abbastanza grande la soluzione corretta dipende dalla quantità di memoria che il nostro server può gestire. –

+0

@Bent Cardan. Questo approccio sembrava essere il migliore e l'ho provato. Ma sto ancora ricevendo un errore 413 dopo circa 20 secondi per un file 4mb. Le mie velocità non sono in grado di gestire 4 MB in 20 secondi, quindi accade dopo che i dati hanno iniziato a scorrere per un bel po '. Pensieri? – Jerome