Intestazione Content-Length contro codifica Chunked

Sto cercando di valutare i vantaggi e gli svantaggi dell’impostazione dell’intestazione HTTP Content-Length rispetto all’uso della codifica Chunked per restituire [probabilmente] file di grandi dimensioni dal mio server. Uno o l’altro è necessario per essere compatibile con le specifiche HTTP 1.1 usando connessioni persistenti. Vedo il vantaggio dell’intestazione Content-Length :

  • Le windows di dialogo di download possono mostrare una barra di avanzamento accurata
  • Il client sa in anticipo se il file potrebbe non essere troppo grande per essere ingerito

Lo svantaggio è dover calcolare la dimensione prima di restituire l’object che non è sempre pratico e potrebbe aggiungere all’utilizzo del server / database. Lo svantaggio della codifica Chunked è il piccolo sovraccarico di aggiungere la dimensione del blocco prima di ogni blocco e la barra di avanzamento del download. qualche idea? Qualche altra considerazione HTTP per entrambi i metodi a cui potrei non aver pensato?

Usa Content-Length, sicuramente. L’utilizzo del server da questo sarà quasi inesistente e il vantaggio per gli utenti sarà grande.

Per i contenuti dinamici, è anche abbastanza semplice aggiungere il supporto per la risposta compressa ( gzip ). Ciò richiede il buffering dell’output, che a sua volta fornisce la lunghezza del contenuto. (non pratico con download di file o contenuto già compresso (audio, immagini)).

Prendi in considerazione anche l’aggiunta del supporto per il contenuto parziale / per la gamma di byte, ovvero la possibilità di riavviare i download. Vedi qui per un esempio di intervallo di byte (l’esempio è in PHP, ma è applicabile in qualsiasi lingua). Hai bisogno di Content-Length quando servi contenuti parziali.

Naturalmente, quelli non sono puntini d’argento: per i media in streaming, è inutile usare il buffering dell’output o le dimensioni della risposta; per i file di grandi dimensioni, il buffering dell’output non ha senso, ma Content-Length e byte serving hanno molto senso (è ansible riavviare un download non riuscito).

Personalmente, servo Content-Length ogni volta che lo so; per il download di file, controllare la dimensione del file è insignificante in termini di risorse. Risultato: l’utente ha una determinata barra di avanzamento (e le pagine dinamiche si scaricano più velocemente grazie a gzip).

Se la lunghezza del contenuto è nota in anticipo, sicuramente la preferirei sopra all’invio in blocchi. Se ci sono mezzi di file statici sul file system del disco locale o in un database, allora qualsiasi linguaggio di programmazione rispettato e RDBMS fornisce modi per ottenere in anticipo la lunghezza del contenuto. Dovresti farne uso.

D’altra parte, se la lunghezza del contenuto è davvero imprevedibile in anticipo (ad esempio quando l’intento è comprimere più file insieme e inviarlo come uno), inviarlo in blocchi potrebbe essere più veloce del buffering nella memoria del server o nella scrittura sul disco locale prima il file system. Ma questo influisce negativamente sull’esperienza utente perché il progresso del download è sconosciuto. L’impaziente può quindi interrompere il download e andare avanti.

Un altro vantaggio della conoscenza della lunghezza del contenuto è la possibilità di riprendere i download. Vedo nella tua cronologia che il tuo linguaggio di programmazione principale è Java; potete trovare qui un articolo con più informazioni tecniche di base e un esempio di servlet Java che lo fa.

Content-Length

L’intestazione Content-Length determina la lunghezza del byte del corpo della richiesta / risposta. Se trascuri di specificare l’intestazione Content-Length , i server HTTP aggiungeranno implicitamente una Transfer-Encoding: chunked intestazione Transfer-Encoding: chunked . L’intestazione Content-Length e Transfer-Encoding non deve essere utilizzata insieme. Il ricevitore non ha idea di quale sia la lunghezza del corpo e non può stimare il tempo di completamento del download. Se si aggiunge un’intestazione Content-Length , assicurarsi che corrisponda all’intero corpo in byte, se non è corretto, il comportamento dei destinatari non è definito.

L’intestazione Content-Length non consente lo streaming, ma è utile per file binari di grandi dimensioni, in cui si desidera supportare la pubblicazione di contenuti parziali. Ciò significa fondamentalmente download ripristinabili, download in pausa, download parziali e download multi-homed. Ciò richiede l’uso di un’intestazione aggiuntiva chiamata Range . Questa tecnica è chiamata servizio Byte .

Transfer-Encoding

L’uso di Transfer-Encoding: chunked è ciò che consente lo streaming all’interno di una singola richiesta o risposta. Ciò significa che i dati vengono trasmessi in modo frammentato e non influiscono sulla rappresentazione del contenuto.

Ufficialmente un client HTTP ha lo scopo di inviare una richiesta con un campo di intestazione TE che specifica quali tipi di codifiche di trasferimento il client è disposto ad accettare. Questo non viene sempre inviato, tuttavia la maggior parte dei server presuppone che i client possano elaborare chunked codifiche chunked .

La codifica di trasferimento chunked fa un uso migliore delle connessioni TCP persistenti, che HTTP 1.1 assume come valore predefinito.

Content-Encoding

È anche ansible comprimere dati chunked o non-chunked. Questo è praticamente fatto tramite l’intestazione Content-Encoding .

Si noti che Content-Length è uguale alla lunghezza del corpo dopo la Content-Encoding del Content-Encoding . Ciò significa che se hai gzipato la tua risposta, il calcolo della lunghezza avviene dopo la compressione. Sarà necessario essere in grado di caricare l’intero corpo in memoria se si desidera calcolare la lunghezza (a meno che non si disponga di tali informazioni altrove).

Durante lo streaming utilizzando la codifica Chunked, l’algoritmo di compressione deve supportare anche l’elaborazione online. Per fortuna, gzip supporta la compressione del stream. Credo che il contenuto venga prima compresso e poi tagliato a pezzi. In questo modo, i blocchi vengono ricevuti, quindi decompressi per acquisire il contenuto reale. Se fosse il contrario, otterrai lo stream compresso, e quindi la decompressione ci darebbe dei pezzi. Il che non ha senso.

Una tipica risposta al stream compresso può avere queste intestazioni:

 Content-Type: text/html Content-Encoding: gzip Transfer-Encoding: chunked 

Semanticamente l’uso di Content-Encoding indica uno schema di codifica “end-to-end”, il che significa che solo il client finale o il server finale dovrebbe decodificare il contenuto. I proxy nel mezzo non sono autorizzati a decodificare il contenuto.

Se si desidera consentire ai proxy nel mezzo di decodificare il contenuto, l’intestazione corretta da utilizzare è in effetti l’intestazione Transfer-Encoding . Se la richiesta HTTP possedeva un header TE: gzip chunked , allora è legale rispondere con Transfer-Encoding: gzip chunked .

Tuttavia questo è molto raramente supportato. Quindi dovresti usare Content-Encoding per la compressione proprio adesso.

Chunked vs Store & Forward