Transfer-Encoding: gzip vs. Content-Encoding: gzip

96

Wie ist der aktuelle Stand der Dinge, wenn es darum geht, ob dies zu tun ist?

Transfer-Encoding: gzip

oder ein

Content-Encoding: gzip

Wenn ich Clients mit z. B. begrenzter Bandbreite erlauben möchte, ihre Bereitschaft zu signalisieren, eine komprimierte Antwort zu akzeptieren, und der Server das letzte Wort darüber hat, ob er komprimiert oder nicht .

Letzteres ist das, was zB Apaches mod_deflate und IIS tun, wenn Sie es für die Komprimierung sorgen lassen. Abhängig von der Größe des zu komprimierenden Inhalts wird dies zusätzlich ausgeführt Transfer-Encoding: chunked.

Es wird auch ein enthalten Vary: Accept-Encoding, das bereits auf das Problem hinweist. Content-Encodingscheint Teil der Entität zu sein, daher bedeutet das Ändern der Content-EncodingBeträge zu einer Änderung der Entität, dh ein anderer Accept-EncodingHeader bedeutet, dass beispielsweise ein Cache seine zwischengespeicherte Version der ansonsten identischen Entität nicht verwenden kann.

Gibt es eine eindeutige Antwort darauf, die ich verpasst habe (und die nicht in einer Nachricht in einem langen Thread in einer Apache-Newsgroup vergraben ist)?

Mein aktueller Eindruck ist:

  • Transfer-Encoding wäre in der Tat der richtige Weg, um das zu tun, was meistens mit Content-Encoding durch vorhandene Server- und Client-Implementierungen gemacht wird
  • Die Inhaltscodierung ist aufgrund ihrer semantischen Auswirkungen mit einigen Problemen verbunden (was sollte der Server tun, ETagwenn er eine Antwort transparent komprimiert?).
  • Der Grund ist Chicken'n'egg: Browser unterstützen es nicht, weil Server dies nicht tun, weil Browser dies nicht tun

Ich gehe also davon aus, dass der richtige Weg ein wäre Transfer-Encoding: gzip(oder, wenn ich den Körper zusätzlich zerhacke, würde es werden Transfer-Encoding: gzip, chunked ). Und in diesem Fall kein Grund zum Berühren Varyoder für ETageinen anderen Header, da es sich um eine Sache auf Transportebene handelt.

Im Moment ist mir das "Hop-by-Hop" -Ness von Transfer-Encodingetwas nicht so wichtig , worüber sich andere in erster Linie Sorgen zu machen scheinen, da Proxys möglicherweise dekomprimiert und unkomprimiert an den Client weitergeleitet werden. Proxys können es jedoch genauso gut weiterleiten wie es ist (komprimiert), wenn die ursprüngliche Anforderung den richtigen Accept-EncodingHeader hat, was bei allen mir bekannten Browsern eine Selbstverständlichkeit ist.

Übrigens ist dieses Problem mindestens ein Jahrzehnt alt, siehe z . B. https://bugzilla.mozilla.org/show_bug.cgi?id=68517 .

Jede Klarstellung hierzu wird geschätzt. Sowohl in Bezug auf das, was als standardkonform angesehen wird, als auch in Bezug auf das, was als praktisch angesehen wird. Beispielsweise wären HTTP-Client-Bibliotheken, die nur transparente "Content-Encoding" unterstützen, ein Argument gegen die Praktikabilität.

Eugene Beresovksy
quelle
2
Siehe auch
Jo Liss
Bin gerade darauf gestoßen. Curl unter PHP 5.3 versteht das nicht Transfer-Encoding:gzip, obwohl das Kommandozeilen-Curl dies nicht tut. Um auf der sicheren Seite zu sein, senden Sie beide, es sei denn, Sie kombinieren Chunked und Gzip.
Seva Alekseyev
1
@SevaAlekseyev beide zu senden wäre sehr falsch - Kunden könnten versuchen, zweimal zu dekomprimieren
Joshua Wise
Dies ist etwas, das mich auch für immer nervt ( Frage, die ich gestellt habe )… gemäß einer der Antworten auf die von @JoLiss zitierte Frage gibt es eine vollkommen logische, semantisch kohärente und standardkonforme Möglichkeit, Anforderungs- / Antwortkörper zu komprimieren… und im Grunde Keine Clients / Server verwenden oder unterstützen es. 🤦🏻‍
Dan Lenski

Antworten:

35

Zitat von Roy T. Fielding , einem der Autoren von RFC 2616:

Eine inkonsistente Änderung der Inhaltscodierung im laufenden Betrieb (weder "nie" noch "immer") macht es unmöglich, dass spätere Anforderungen bezüglich dieses Inhalts (z. B. PUT oder bedingtes GET) korrekt behandelt werden. Dies ist natürlich der Grund für die Ausführung On-the-Fly-Inhaltscodierung ist eine blöde Idee, und warum ich HTTP Transfer-Encoding hinzugefügt habe, um die On-the-Fly-Codierung ohne Änderung der Ressource durchzuführen.

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

Mit anderen Worten: Do not do on-the-fly Content-Encoding, Verwendung Transfer-Encoding statt!

Bearbeiten: Das heißt, es sei denn, Sie möchten Clients, die nur die Inhaltscodierung verstehen, komprimierten Inhalt bereitstellen . Was leider die meisten von ihnen zu sein scheinen. Beachten Sie jedoch, dass Sie den Bereich der Spezifikation verlassen und möglicherweise auf Probleme wie das von Fielding und anderen erwähnte stoßen, z. B. wenn Caching-Proxys beteiligt sind.

Eugene Beresovsky
quelle
3
Wenn ich es richtig verstehe: 1. Die Inhaltscodierung bezieht sich auf die Inhaltscodierung auf dem Server in der Zusammenfassung, dh der Inhalt wird vom Server konsistent in der angegebenen Codierung bereitgestellt. 2. Die Übertragungscodierung bezieht sich auf die Codierung, die der Server verwendet, um sie in diesem Fall an den Benutzeragenten zu übermitteln, dh in dieser Antwort. Stellen Sie nur sicher, dass ich Ihre Antwort nicht falsch interpretiere.
Dot Slash Hack
28
@KemHeyndels Ungefähr richtig. Anders ausgedrückt: Nach den Angaben, Transfer-Encoding ist eine reine Transportschicht Detail , das heißt ein Zwischen Proxy ist frei rückgängig zu machen zB gzip - Komprimierung auf diesem Niveau, während Content-Encoding a Business - Schicht - Eigenschaft , die ein Proxy nicht wäre darf sich zusätzlich zu anderen Auswirkungen (ETags usw.) ändern. Nach der Realität jedoch ist TE die normalerweise nicht für die Kompression verwendet, und viele Server / Clients selbst es nicht aus der Box heraus stützen,, während CE mehr oder weniger die Art und Weise verwendet wird TE intented wurde verwendet werden : als Transportschicht Detail .
Eugene Beresovsky
1
Die Realität verpflichtet uns also, den Rat von Roy T. Fielding zu ignorieren?
Dot Slash Hack
11
@KemHeyndels Der Idealismus verpflichtet Sie, zunächst allen Open-Source-HTTP-Client / Server-Implementierungen TE-Unterstützung hinzuzufügen. Dann beschäftigen Sie sich bei jedem Unternehmen mit Closed-Source-HTTP-Implementierungen (ich denke, das ist sowieso nur Microsoft) und fügen Sie die Funktion dort hinzu. Danach werden Realität und Spezifikation zusammenfallen. ;) (Und HTTP 2.0 wird veröffentlicht, wodurch das Problem trotzdem
Eugene Beresovsky
10
Wenn Sie angeben, dass Sie Transfer-Encoding unterstützen, wird immer noch nicht klar, dass Sie gzip über Transfer-Encoding unterstützen, sodass Sie nichts kaufen. Die Anzeige erfolgt umgekehrt : Jeder Client, der gzip über Transfer-Encoding ausführen kann, teilt dies dem Server durch Einstellung mit TE: gzip. Und dann sollte Ihr Server den Transfer-Encoding-Weg gehen. Wenn der Kunde nur sagt Accept-Encoding: gzip, müssen Sie es Content-Encodingso machen. Wenn der Client in seiner Anforderung keine der beiden Angaben macht, darf der Server überhaupt nicht gzip.
Eugene Beresovsky
27

Die korrekte Verwendung, wie in RFC 2616 definiert und tatsächlich in freier Wildbahn implementiert, besteht darin, dass der Client einen Accept-EncodingAnforderungsheader sendet (der Client kann mehrere Codierungen angeben). Der Server kann dann und nur dann die Antwort gemäß den vom Client unterstützten Codierungen codieren (wenn die Dateidaten nicht bereits in dieser Codierung gespeichert sind) und im Antwortheader angeben, Content-Encodingwelche Codierung verwendet wird. Der Client kann dann Daten basierend auf dem Transfer-Encoding(dh chunked) aus dem Socket lesen und sie dann basierend auf dem Content-Encoding(dh :) dekodieren gzip.

In Ihrem Fall würde der Client also einen Accept-Encoding: gzipAnforderungsheader senden , und dann könnte der Server entscheiden, (falls nicht bereits) zu komprimieren und einen Content-Encoding: gzipund optional einen Antwortheader zu senden Transfer-Encoding: chunked.

Und ja, der Transfer-EncodingHeader kann in Anforderungen verwendet werden, jedoch nur für HTTP 1.1, was erfordert, dass sowohl Client- als auch Server-Implementierungen die chunkedCodierung in beide Richtungen unterstützen.

ETagIdentifiziert die Ressourcendaten auf dem Server eindeutig, nicht die tatsächlich übertragenen Daten. Wenn eine bestimmte URL-Ressource ihren ETagWert ändert , bedeutet dies, dass sich die serverseitigen Daten für diese Ressource geändert haben.

Remy Lebeau
quelle
14
Die Inhaltscodierung ist ein Merkmal der Entität, die durch die Anforderungs-URI identifiziert wird. Mit anderen Worten: Unterschiedlich Content-Encodingerfordert unterschiedlich.ETag Dies ist übrigens der mod_deflate-Fehler, auf den ich in meiner Antwort verweise. Ich frage mich, warum dieses Detail auf Anwendungsebene überhaupt im HTTP-Standard enthalten ist. Wenn Sie Transfer-Encodingjedoch eine Einstellung für die Transportebene verwenden, müssen Sie die nicht ändern ETag. Außer niemand hat Transfer-Enc implementiert.
Eugene Beresovsky
2
Die Inhaltscodierung ist nicht für die "on the fly" -Codierung vorgesehen. In RFC 2616 heißt es: "Die Übertragungscodierung ... unterscheidet sich von der Inhaltscodierung darin, dass die Übertragungscodierung eine Eigenschaft der Nachricht und nicht der Entität ist." ( Tools.ietf.org/html/rfc2616#section-14.41 ) und "Die Inhaltscodierung ist ein Merkmal der durch die Anforderungs-URI identifizierten Entität. In der Regel wird der Entitätskörper mit dieser Codierung gespeichert" ( tools.ietf.org/html/rfc2616#section-14.11 ). Also stimme ich ab.
Robert
Was I beschrieben ist , was „ tatsächlich in der freien Natur umgesetzt “, unabhängig von Content-Encodingvs Transfer-Encoding. Ja, gzip sollte eine Eigenschaft der Übertragung einer Ressource sein, wenn dies im laufenden Betrieb erfolgt. Wenn die Ressource jedoch komprimiert auf dem Server gespeichert ist, sollte sie stattdessen eine Eigenschaft des Inhalts der Ressource sein, wenn sie unverändert gesendet wird. Aber was sein sollte und was eigentlich ist, ist nicht immer dasselbe.
Remy Lebeau