Codifica trasferimento: gzip vs. codifica contenuto: gzip


98

Qual è lo stato attuale delle cose quando si tratta di fare o meno

Transfer-Encoding: gzip

o a

Content-Encoding: gzip

quando voglio consentire ai client con una larghezza di banda limitata, ad esempio, di segnalare la loro disponibilità ad accettare una risposta compressa e il server ha l'ultima parola se comprimere o meno .

Quest'ultimo è ciò che, ad esempio, mod_deflate e IIS di Apache fanno, se si lascia che si occupi della compressione. A seconda della dimensione del contenuto da comprimere, farà l'addizionale Transfer-Encoding: chunked.

Includerà anche un Vary: Accept-Encoding, che già accenna al problema. Content-Encodingsembra essere parte dell'entità, quindi modificare gli Content-Encodingimporti in una modifica dell'entità, ovvero Accept-Encodingun'intestazione diversa significa, ad esempio, che una cache non può utilizzare la sua versione memorizzata nella cache dell'entità altrimenti identica.

C'è una risposta definitiva su questo che mi sono perso (e che non è sepolta all'interno di un messaggio in un lungo thread in qualche newsgroup di Apache)?

La mia impressione attuale è:

  • Transfer-Encoding sarebbe infatti il ​​modo giusto per fare ciò che viene fatto principalmente con Content-Encoding da implementazioni di server e client esistenti
  • La codifica del contenuto, a causa delle sue implicazioni semantiche, comporta un paio di problemi (cosa dovrebbe fare il server ETagquando comprime in modo trasparente una risposta?)
  • Il motivo è chicken'n'egg: i browser non lo supportano perché i server no perché i browser no

Quindi presumo che il modo giusto sarebbe un Transfer-Encoding: gzip(o, se anche un altro pezzo del corpo, diventerebbe Transfer-Encoding: gzip, chunked ). E non c'è motivo di toccare Varyo ETago qualsiasi altra intestazione in quel caso poiché è una cosa a livello di trasporto.

Per ora non mi interessa molto del 'hop-by-hop' Transfer-Encoding, qualcosa di cui gli altri sembrano preoccuparsi prima di tutto, perché i proxy potrebbero decomprimersi e inoltrare non compressi al client. Tuttavia, i proxy potrebbero altrettanto bene inoltrarlo così com'è (compresso), se la richiesta originale ha l' Accept-Encodingintestazione corretta , che nel caso di tutti i browser che conosco è un dato di fatto.

A proposito, questo problema ha almeno un decennio, vedere ad esempio https://bugzilla.mozilla.org/show_bug.cgi?id=68517 .

Ogni chiarimento in merito sarà gradito. Sia in termini di ciò che è considerato conforme agli standard che di ciò che è considerato pratico. Ad esempio, le librerie client HTTP che supportano solo la "Content-Encoding" trasparente sarebbero un argomento contro la praticità.



Mi sono imbattuto in questo. Curl su PHP 5.3 non capisce Transfer-Encoding:gzip, anche se curl da riga di comando lo fa. Per sicurezza, invia entrambi, a meno che tu non stia combinando chunked e gzip.
Seva Alekseyev

1
@SevaAlekseyev l'invio di entrambi sarebbe molto sbagliato - i clienti potrebbero provare a decomprimere due volte
Joshua Wise,

Questo è qualcosa che mi ha infastidito per sempre ( domanda che ho posto ) ... per una delle risposte alla domanda citata da @JoLiss, c'è un modo perfettamente logico, semanticamente coerente e conforme agli standard per comprimere i corpi di richiesta / risposta ... e fondamentalmente nessun client / server lo utilizza o lo supporta. 🤦🏻‍
Dan Lenski,

Risposte:


35

Citando Roy T. Fielding , uno degli autori della RFC 2616:

la modifica al volo della codifica del contenuto in modo incoerente (né "mai" né "sempre) rende impossibile gestire correttamente le richieste successive riguardanti quel contenuto (ad es. PUT o GET condizionale). Questo è, ovviamente, il motivo per cui eseguire la codifica dei contenuti al volo è un'idea stupida e perché ho aggiunto Transfer-Encoding a HTTP come modo corretto per eseguire la codifica al volo senza modificare la risorsa.

Fonte: https://issues.apache.org/bugzilla/show_bug.cgi?id=39727#c31

In altre parole: non eseguire la codifica dei contenuti al volo , usa invece la codifica del trasferimento!

Modifica: Cioè, a meno che tu non voglia servire contenuto gzippato a client che comprendono solo Content-Encoding . Che, sfortunatamente, sembra essere la maggior parte di loro. Ma tieni presente che lasci i regni delle specifiche e potresti incorrere in problemi come quello menzionato da Fielding e altri, ad esempio quando sono coinvolti i proxy di cache.


3
Quindi, se ho capito bene: 1. La codifica del contenuto si riferisce alla codifica del contenuto sul server in astratto, cioè il contenuto sarà costantemente servito nella codifica specificata dal server. 2. La codifica di trasferimento si riferisce alla codifica che il server ha deciso di utilizzare per consegnarla al programma utente in questo caso, cioè in questa risposta. Mi sto solo assicurando di non interpretare male la tua risposta.
trucchetto punto barra

30
@KemHeyndels A proposito di destra. In altre parole: secondo le specifiche, Transfer-Encoding è un puro dettaglio del livello di trasporto , ovvero un proxy intermedio è libero di annullare, ad esempio, la compressione gzip a quel livello, mentre Content-Encoding è una proprietà del livello aziendale , che un proxy non sarebbe permesso di cambiare, oltre ad altre ramificazioni (ETags ecc.). Secondo la realtà , tuttavia, TE non viene normalmente utilizzato per la compressione e molti server / client non lo supportano nemmeno immediatamente, mentre CE viene utilizzato più o meno nel modo in cui si intendeva utilizzare TE : come dettaglio del livello di trasporto .
Evgeniy Berezovsky

1
Quindi siamo obbligati dalla realtà a ignorare il consiglio di Roy T. Fielding?
trucchetto punto barra

11
@KemHeyndels Sei obbligato dall'idealismo a uscire e prima aggiungere il supporto TE a tutte le implementazioni client / server HTTP open-source. Quindi fatti assumere in ogni azienda che ha implementazioni HTTP closed-source (penso che sia comunque solo Microsoft) e aggiungi la funzionalità anche lì. Dopodiché, la realtà e le specifiche coincideranno. ;) (E HTTP 2.0 sarà stato rilasciato, eliminando comunque il problema)
Evgeniy Berezovsky

10
Indicare che supporti Transfer-Encoding ancora non chiarisce che supporti gzip su Transfer-Encoding, quindi questo non ti fa guadagnare nulla. L'indicazione viene eseguita al contrario : qualsiasi client che può eseguire gzip tramite Transfer-Encoding lo informerà del server impostando TE: gzip. E poi il tuo server dovrebbe seguire la rotta Transfer-Encoding. Se il cliente dice solo Accept-Encoding: gzip, devi farlo nel Content-Encodingmodo in cui. Se il client non specifica né l'uno né l'altro nella sua richiesta, il server non deve assolutamente eseguire il gzip.
Evgeniy Berezovsky

27

L' utilizzo corretto , come definito nella RFC 2616 e effettivamente implementato in natura, è che il client invii Accept-Encodingun'intestazione di richiesta (il client può specificare più codifiche). Il server può quindi, e solo allora, codificare la risposta in base alle codifiche supportate dal client (se i dati del file non sono già memorizzati in quella codifica), indicare nell'intestazione della Content-Encodingrisposta quale codifica viene utilizzata. Il client può quindi leggere i dati dal socket in base a Transfer-Encoding(ie, chunked) e quindi decodificarli in base a Content-Encoding(ie:) gzip.

Quindi, nel tuo caso, il client invierà Accept-Encoding: gzipun'intestazione di richiesta, quindi il server potrebbe decidere di comprimere (se non lo è già) e inviare un'intestazione di risposta Content-Encoding: gzipe facoltativamente Transfer-Encoding: chunked.

E sì, l' Transfer-Encodingintestazione può essere utilizzata nelle richieste, ma solo per HTTP 1.1, che richiede che le implementazioni client e server supportino la chunkedcodifica in entrambe le direzioni.

ETagidentifica in modo univoco i dati delle risorse sul server, non i dati effettivamente trasmessi. Se una determinata risorsa URL cambia il suo ETagvalore, significa che i dati lato server per quella risorsa sono cambiati.


14
la codifica del contenuto è una caratteristica dell'entità identificata dall'URI della richiesta In altre parole: Diverso Content-Encodingrichiede diversoETag Questo è a proposito del bug mod_deflate a cui mi riferisco nella mia risposta. Mi chiedo perché questo dettaglio a livello di applicazione sia nello standard HTTP in primo luogo. Transfer-EncodingTuttavia, quando si utilizza un'impostazione del livello di trasporto, non è necessario modificare il file ETag. Tranne che nessuno ha implementato Transfer-Enc.
Evgeniy Berezovsky

2
Content-Encoding non è per la codifica "al volo". RFC 2616 dice "La codifica del trasferimento ... differisce dalla codifica del contenuto in quanto la codifica del trasferimento è una proprietà del messaggio, non dell'entità." ( Tools.ietf.org/html/rfc2616#section-14.41 ) e "La codifica del contenuto è una caratteristica dell'entità identificata dall'URI della richiesta. In genere, il corpo dell'entità è memorizzato con questa codifica" ( tools.ietf.org/html/rfc2616#section-14.11 ). Quindi voto contro.
Robert il

Quello che ho descritto è ciò che è " effettivamente attuato in the wild ", a prescindere dal Content-Encodingvs Transfer-Encoding. Sì, gzip dovrebbe essere una proprietà del trasferimento di una risorsa, se eseguito al volo. D'altra parte, se la risorsa è archiviata compressa sul server, dovrebbe invece essere una proprietà del contenuto della risorsa, se inviata così com'è. Ma ciò che dovrebbe essere e ciò che è effettivamente non sono sempre la stessa cosa.
Remy Lebeau
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.