A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.
1 <?xml version="1.0" encoding="iso-8859-1" ?> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 3 <html xmlns="http://www.w3.org/1999/xhtml"> 4 5 <head> 6 <title>Zwischenspeicherung mod_gzip-komprimierter Daten durch Proxy-Server</title> 7 <meta name="author" content="Michael Schröpl" /> 8 <meta name="description" content="Eine Diskussion der Probleme eines Proxy-Servers bei der korrekten Verarbeitung während der Zwischenspeicherung komprimierter HTTP-Daten sowie der erforderlichen Kooperation durch den HTTP-Server" /> 9 <meta name="keywords" content="Apache, HTTP, Kodierung, gzip, Komprimierung, Proxy, Cache" /> 10 <style type="text/css"> 11 body{font-family:sans-serif;margin:0px 30px 0px 30px;} 12 h1{font-size:22px;margin-top:20px;} 13 h2{font-size:18px;margin-top:14px;} 14 small{font-size:80%;} 15 td{vertical-align:top;} 16 tt{font-weight:bold;} 17 code,tt{font-family:"Courier New",monospace;} 18 h1,h2{margin-bottom:1px;} 19 p,td{margin-top:3px;margin-bottom:3px;} 20 p,ul,ol,li{font-size:17px;line-height:22px;} 21 ul,ol,li{margin-top:0px;margin-bottom:0px;} 22 img{border-width:0;} 23 24 #nav{position:absolute;top:30px;left:0px;font-size:14px;width:170px;font-weight:bold;margin:2px 2px 2px 30px;} 25 #nav[id]{position:fixed;} 26 #nav img{margin:5px;} 27 #nav p, #nav a:hover, #nav a{display:block;padding:3px;margin:2px;width:150px;font-size:15px;line-height:18px;} 28 #content{position:absolute;left:220px;right:30px;} 29 #mail{text-align:right;} 30 #icon{width:190px;float:left;} 31 #mail,#icon{margin-top:30px;} 32 33 @media screen { 34 body{color:#000;background-color:#f8ebd9;} 35 h1{color:#666;} 36 h2{color:#840;} 37 code{color:#333;} 38 em{color:#900;} 39 tt{color:#909;} 40 h1,h2,code,em,tt{background-color:inherit;} 41 .new13192a{color:#inherit;background-color:#ffd;} 42 .new13261a{color:#inherit;background-color:#eff;} 43 .bugfix{color:#fff;background-color:#f00;font-weight:bold;padding:0px 4px;} 44 #nav a{color:#530;background-color:transparent;} 45 #nav a{text-decoration:none;} 46 #nav p, #nav a:hover{color:#000;background-color:#fff;} 47 #nav p {border:1px #660 solid;} 48 #nav a {border:1px #666 dotted;} 49 } 50 51 @media print { 52 #icon,#nav{display:none;} 53 #content{position:absolute;left:0px;right:0px;} 54 } 55 </style> 56 </head> 57 58 <body> 59 60 <div id="nav"> 61 62 <img src="mod_gzip_logo.gif" height="47" width="102" alt="mod_gzip-Logo" /> 63 64 65 <a title="mod_gzip - was ist das überhaupt?" href="index.htm">mod_gzip</a> 66 67 68 69 <a title="Komprimierung von HTTP-Inhalten durch Content-Encoding" href="encoding.htm">Content-Encoding</a> 70 71 72 73 <a title="Welche Browser können mit 'Content-Encoding: gzip' umgehen?" href="browser.htm">Browser</a> 74 75 76 77 <a title="Wie gehen Firewall mit 'Content-Encoding: gzip' um?" href="firewalls.htm">Firewalls</a> 78 79 80 81 <a title="Eine Beispiel-Konfiguration für mod_gzip" href="config.htm">Konfiguration</a> 82 83 84 85 <a title="Beschreibung sämtlicher mod_gzip-Status-Codes" href="status.htm">Status-Codes</a> 86 87 88 89 <a title="Mögliche Erweiterungen in künftigen Versionen von mod_gzip" href="enhancements.htm">Erweiterungen</a> 90 91 92 93 <p>Caching</p> 94 95 96 97 <a title="Versions-Historie und Änderungsprotokoll von mod_gzip" href="versions.htm">Versionen</a> 98 99 100 101 <a title="Andere Quellen zu mod_gzip" href="links.htm">Links</a> 102 103 104 </div> 105 106 <div id="content"> 107 108 <h1>Zwischenspeicherung mod_gzip-komprimierter Daten durch Proxy-Server</h1> 109 110 <h2><a name="negotiation"></a>Komprimierung durch Verhandlung</h2> 111 <p>Die Verwendung einer konfigurierbaren Komprimierungs-Funktion wie <tt>mod_gzip</tt> ist letzten Endes immer eine Art von Content-Negotiation, also eine bedingte Auslieferung unterschiedlicher Inhalte für denselben angeforderten URL, in Abhängigkeit von bestimmten Angaben des HTTP-Headers.</p> 112 <p>HTTP erlaubt allerdings die <strong>Zwischenspeicherung</strong> von Antworten auf HTTP-Requests in Caches, insbesondere bei Verwendung von Proxy-Servern. Wenn nun</p> 113 <ol> 114 <li>ein HTTP-Client eine Anforderung sendet,</li> 115 <li>die entsprechende Antwort in komprimierter Form ausgeliefert und von einem Proxy gespeichert wird und</li> 116 <li>anschließend ein anderer HTTP-Client eine Anforderung für denselben URL stellt,</li> 117 </ol> 118 <p>dann hat der Proxy-Server - ohne im Besitz weiterer Informationen zu sein - ein Problem:</p> 119 <ul> 120 <li>Darf er den gespeicherten Inhalt auch an diesen zweiten HTTP-Client senden, oder</li> 121 <li>muß er die Anforderung an den HTTP-Server weiterleiten?</li> 122 </ul> 123 <p>Denn nur der HTTP-Server kann <small>(aufgrund seiner Konfiguration mit entsprechenden Filter-Regeln)</small> letzten Endes herausfinden, ob auch der zweite HTTP-Client komprimierte Daten als Antwort erhalten darf.</p> 124 <p>Dies ist übrigens <em>kein</em> Effekt der Verwendung eines Komprimierungsverfahrens allein, sondern ein allgemeines Problem der Zwischenspeicherung von HTTP-Daten, deren Inhalt nicht eindeutig durch einen URL beschrieben sein kann, im Cache eines Proxy-Servers und ähnliche mit einem Gedächtnis ausgestattete Server auf dem Transportweg. Dies schließt Verhandlungsprozeduren aller Art ebenso mit ein wie die Übertragung zusätzlicher Informationen innerhalb der HTTP-Header, etwa Server-Authentification oder Cookies.</p> 125 126 <h2><a name="performance"></a>Performance-Anforderungen</h2> 127 <p>Natürlich kann man versuchen, das Problem dadurch zu umgehen, indem man allen auf dem Weg zwischen Client und Server befindlichen Proxy-Servern explizit <em>verbietet</em>, die Daten der entsprechenden Antwort zu speichern <small>(durch den Einsatz entsprechender HTTP-Header <code>Expires:</code> und <code>Pragma:</code> in HTTP/1.0 bzw. <code>Cache-Control:</code> in HTTP/1.1)</small>.</p> 128 <p>Aber der Zweck der Komprimierung ist es, die Übertragung der Daten <small>(durch die Reduzierung der Datenmenge)</small> zu beschleunigen - und die Zwischenspeicherung von Daten dient demselben Zweck <small>(durch die Reduzierung der Zugriffe auf den HTTP-Server)</small>. Und es sollte nicht die eine Performance-Optimierung dazu führen, daß die andere nicht mehr eingesetzt werden kann, insbesondere da im vorliegenden Fall beide einander nicht ersetzen, sondern <strong>gegenseitig wirkungsvoll ergänzen</strong> können.</p> 129 130 <h2><a name="parameters"></a>Informationen über Verhandlungs-Parameter</h2> 131 <p>Die HTTP-Spezifikation enthält die Definition des <strong>HTTP-Headers <code>Vary</code></strong>, wodurch der HTTP-Server den Proxy-Server darüber informieren kann,</p> 132 <ul> 133 <li>ob eine Antwort das <em>eindeutige</em> Ergebnis der Anforderung eines URL war oder</li> 134 <li>ob andere Eigenschaften einer Anforderung desselben URLs zu <em>abweichenden</em> Ergebnissen führen können.</li> 135 </ul> 136 <p>Sein Wert kann eine Liste von <strong>Namen anderer HTTP-Header</strong> enthalten, deren Inhalt für die Auslieferung gerade dieser Antwort auf eine Anforderung entscheidend war. Der HTTP-Server kann dem Proxy-Server also sogar mitteilen, <em>welche</em> HTTP-Header die Entscheidung über den ausgelieferten Inhalt beeinflußt haben.</p> 137 <p>Wenn ein Proxy-Server eine Anforderung zu einem HTTP-Server weiterleitet und später die Antwort in seinem Cache speichern will, dann sollte er noch im Besitz der HTTP-Header der ursprünglichen Anforderung sein, wenn die Antwort des HTTP-Servers eintrifft.</p> 138 <p>Falls nun der HTTP-Server einen bedingten Inhalt einer Antwort durch den entsprechenden <code>Vary</code>-Header kennzeichnet,</p> 139 <ul> 140 <li>muß der Proxy-Server nicht nur den Inhalt dieser Antwort, sondern auch alle Informationen der relevanten HTTP-Header <small>(deren Namen in der Werteliste des HTTP-Headers <code>Vary</code> der Antwort aufgeführt sind)</small> aus der Anforderung in seinem Cache abspeichern, und</li> 141 <li>er darf diesen gespeicherten Inhalt nur dann als Antwort auf weitere Anforderungen ausliefern, falls die Informationen der entsprechenden HTTP-Header einer solchen weiteren Anforderung zu denen der ursprünglichen Anforderung 'paßt', d. h. <em>für jeden einzelnen dieser Header semantisch mit dem Wert des Original-Requests übereinstimmt</em>.</li> 142 </ul> 143 144 <h2><a name="restrictions"></a>Resultierende Einschränkungen für den HTTP-Server</h2> 145 <p>Die vorherigen Ausführungen haben gezeigt, wie ein Proxy-Server die bedingte Auslieferung von HTTP-Antworten <small>(die das Ergebnis einer Content-Negotiation darstellen)</small> korrekt und gleichzeitig mit maximaler Ausnutzung seines Zwischenspeicher-Effekts behandeln kann - unter der Voraussetzung, daß</p> 146 <ul> 147 <li>der HTTP-Server den Proxy-Server mit ausreichenden Informationen über die Parameter der Verhandlung versorgt und</li> 148 <li>daß dem Proxy-Server die entsprechenden Informationen bei einer nachfolgenden Anforderung desselben URL durch einen weiteren HTTP-Client zur Verfügung stehen können.</li> 149 </ul> 150 <p>Letzteres bedeutet nun aber eine Einschränkung für die Freiheitsgrade des Verhandlungsvorgang. Denn wenn der Proxy-Server <em>ausschließlich</em> anhand von Informationen innerhalb einer HTTP-Anforderung entscheiden muß, ob er seinen Cache-Inhalt ausliefern darf oder nicht, dann dürfen sich die Verhandlungsregeln des HTTP-Servers ausschließlich auf Inhalte der HTTP-Header beziehen!</p> 151 <p>Diese Voraussetzung erfüllt <tt>mod_gzip</tt> nun aber leider nicht. Denn von den dort möglichen sechs Klassen von Filter-Regeln beziehen sich</p> 152 <ul> 153 <li>zwei 'legale' <small>(<code>reqheader</code> und <code>uri</code>)</small> ausschließlich auf Inhalte des HTTP-Headers, aber</li> 154 <li>vier andere 'illegale' <small>(<code>rspheader</code>, <code>handler</code>, <code>file</code> und <code>mime</code>)</small> auf Informationen, welche <em>erst während der Auswertung der Anforderung durch den HTTP-Server verfügbar</em> werden.</li> 155 </ul> 156 <p>Verwendet ein Server, der um <tt>mod_gzip</tt> erweitert wurde, also eine dieser 'illegalen' Filterregeln, dann <em>kann</em> der Proxy-Server nicht mehr in der Lage sein, korrekt über die Verwendbarkeit seines Cache-Inhalts zur Beantwortung weiterer Anforderungen zu entscheiden.</p> 157 <p>Dabei nützt es dem Proxy-Server auch wenig, wenn <tt>mod_gzip</tt> den Proxy-Server darauf aufmerksam machen würde, daß dieser offensichtlich überfordert sein wird <small>(durch eine vollständige Liste der für diese Anforderung signifikanten Filterregelklassen innerhalb eines <code>Vary:</code>-Headers, falls <em>dies</em> denn erlaubt wäre)</small>. Alles, was der Proxy-Server tun könnte, wäre, das Auftreten einer der vier 'illegalen' Filterregelklassen als Kriterium zu verwenden, den Inhalt der Antwort nicht zwischenzuspeichern.</p> 158 <p>Das allein wäre nicht weiter schlimm - solange HTTP-Server sich darauf beschränkt, ausschließlich 'legale' Regeln zu verwenden, würde sein Server mit einem Proxy-Server optimal kooperieren können.</p> 159 <p>Leider ist jedoch genau dies mit <code>mod_gzip 1.3.19.1a</code> unmöglich.</p> 160 <p>Die Einbettung von <code>mod_gzip 1.3.19.1a</code> in die Architektur von Apache 1.3 erfolgt auf eine relativ komplexe Art und Weise:</p> 161 <ul> 162 <li>In Phase 1 der Verarbeitung prüft <tt>mod_gzip</tt>, ob es sich überhaupt für die Verarbeitung des Ergebnisses dieser Anforderung interessieren und entsprechende Vorbereitungen dafür treffen sollte - aufgrund der Regeln von vier Klassen <small>(<code>reqheader</code>, <code>uri</code>, <code>file</code> und <code>handler</code>, d. h. zwei 'legale' und zwei 'illegale' Regelklasse)</small>.</li> 163 <li>In Phase 2 der Verarbeitung prüft <tt>mod_gzip</tt>, ob es nun tatsächlich den <small>(inzwischen vorliegenden)</small> Inhalt der Antwort komprimieren soll - aufgrund der Regeln von zwei Klassen <small>(<code>rspheader</code> und <code>mime</code>, beides 'illegale' Regelklassen)</small>.</li> 164 </ul> 165 <p>Für die erfolgreiche Zulassung einer Anforderung zur Komprimierung ist mindestens die Erfüllung je einer <code>include</code>-Regel aus <em>jeder der beiden Phasen</em> erforderlich <small>(und die Nicht-Erfüllung aller <code>exclude</code>-Regeln)</small>.</p> 166 <p>Da aber <em>beide</em> <code>include</code>-Regelklassen aus Phase 2 'illegal' sind, <em>muß</em> jede Liste der relevanten Filterklassen für eine erfolgreiche Komprimierung in der aktuellen Implementierung von <tt>mod_gzip</tt> mindestens eine 'illegale' Regelklasse umfassen.</p> 167 <p>Somit ist es unmöglich, einen Proxy-Server mit Informationen zu versorgen, welche dieser für die Entscheidung über die Nutzbarkeit eines Cache-Inhalts verwenden kann - die übermittelten Informationen werden das Verstädnis des Proxy-Servers <em>immer</em> übersteigen.</p> 168 169 <h2><a name="encodings"></a>Verallgemeinerung auf beliebige HTTP-Content-Encodings</h2> 170 <p>Dasselbe gilt letzten Endes für jeden HTTP-Header, der Element einer Verhandlung ist. Und die Kombination mehrerer HTTP-Header als Verhandlungs-Aspekte würde zu einem exponentiellen Wachstum der im Cache parallel zu haltenden Varianten führen.</p> 171 <p>Dennoch sprechen einige Argumente dafür, einen solchen Ansatz zu verfolgen:</p> 172 <ul> 173 <li>Die Funktion eines Caching Proxy ist es, die Ressource 'Bandbreite' durch den Einsatz der Ressource 'Speicherkapazität' zu kompensieren. Es darf also vorausgesetzt werden, daß ein solcher Zwischenspeicher mit einem hohen Maß an Speicherkapazität ausgestattet ist, um bei bestimmten Dokumenten auch eine große Anzahl von Varianten aufnehmen zu können.</li> 174 <li>Es ist zu vermuten, daß nur ein geringer Anteil der Menge aller Dokumente das Ergebnis einer Verhandlung zwischen Server und Client sein werden. Somit würde der Speicherbedarf für eine flexiblere Handhabung von Varianten innerhalb des Zwischenspeichers nicht direkt proportional zum Gesamtvolumen der gespeicherten Dokumente wachsen.</li> 175 <li>Falls trotz dieser Einschränkungen eine Darstellung sämtlicher Permutationen von Verhandlungs-Attributen die Kapazität eines Zwischenspeichers übersteigen würde, besteht immer noch die Möglichkeit, dies durch etablierte Algorithmen <small>(Verdrängung der am längsten nicht nachgefragten Varianten)</small> oder auch durch die Definition von Prioritäten zu steuern.</li> 176 <li>Zudem ist das Betriebsziel eines Caching Proxy die Beschleunigung der Übertragung von Daten. Wenn ein solcher Zwischenspeicher die Möglichkeit erhält, mit einem anderen Verfahren zur Beschleunigung der Datenübertragung zu kooperieren, dann sollte er daran interessiert sein, dies zu tun. Dies könnte bedeuten, daß das Content-Encoding gegenüber anderen Verhandlungs-Aspekten gespeicherter Daten bevorzugt werden sollte.</li> 177 </ul> 178 <p>Das genaue Verfahren ist keine Frage der Standardkonformität, sondern lediglich der maximalen Leistungsfähigkeit des Zwischenspeichers - hierbei sind sicherlich Konfigurationsmöglichkeiten vorzusehen und Erfahrungswerte über tatsächliche Anforderungen verhandelbarer Daten zu berücksichtigen.</p> 179 180 <div class="new13192a"> 181 182 <h2><a name="vary-1.3.19.2a"></a><code>Vary</code>-Header in <tt>mod_gzip</tt> seit 1.3.19.2a</h2> 183 <p>Beginnend mit der Version 1.3.19.2a sendet <tt>mod_gzip</tt> <code>Vary:</code>-Header - und zwar bei <em>jeder</em> Anforderung, bei deren Verarbeitung das Modul wenigstens einmal aktiviert wurde <small>(unabhängig davon, ob dabei komprimierte Daten ausgeliefert wurden oder nicht)</small>.</p> 184 <p>Bei diesem Erkenntnisstand von <tt>mod_gzip</tt> ist <em>jede</em> Anforderung <small>(unabhängig davon, ob die Antwort tatsächlich komprimiert ausgeliefert wurde oder nicht)</small> potentiell eine Verhandlung:</p> 185 <ul> 186 <li>mindestens über den HTTP-Header <code>Accept-Encoding</code> und</li> 187 <li>möglicherweise auch über weitere HTTP-Header <small>(nämlich all diejenigen, welche innerhalb von Filterregeln der Klasse <code>reqheader</code> auftreten)</small></li> 188 </ul> 189 <p><tt>mod_gzip</tt> kann derzeit <em>noch nicht</em> die optimalen <code>Vary:</code>-Header, nämlich deren minimal erforderlichen Umfang, erzeugen - dafür wäre es erforderlich, das Auswertungsverfahren für Filterregeln komplett umzuschreiben.</p> 190 <p>Als ersten Schritt sendet das Modul seit <a href="version.htm#v1.3.19.2a">Version 1.3.19.2a</a> einen <code>Vary:</code>-Header, der</p> 191 <ul> 192 <li>die Angabe <code>Accept-Encoding</code> sowie</li> 193 <li>die Namen sämtlicher innerhalb beliebiger <code>reqheader</code>-Regeln verwendeten Header</li> 194 </ul> 195 <p>enthält, denn jede dieser Regeln könnte den Ausschlag für das Ergebnis der Verhandlung geben, und in jedem dieser Fälle wäre das Ergebnis vom Inhalt des empfangenen HTTP-Headers abhängig. Dies kann natürlich in bestimmten Fällen viel zuviel sein <small>(und dann die wirkungsvolle Zwischenspeicherung von Inhalten massiv behindern)</small>, aber es ist wenigstens mal ein Anfang.</p> 196 197 </div> 198 199 <div class="new13261a"> 200 201 <p><a name="vary-1.3.26.1a"></a>Als Verbesserung dieser Vorgehensweise sendet <a href="versions.htm#v1.3.26.1a"><tt>mod_gzip</tt> 1.3.26.1a</a> <em>keinen</em> <code>Vary:</code>-Header, falls die Komprimierung dieser Anforderung durch eine <a href="config.htm#filters"><code>mod_gzip_item_exclude</code>-Regel</a> des Typs</p> 202 <ul> 203 <li><code>file</code></li> 204 <li><code>uri</code> bzw.</li> 205 <li><code>handler</code></li> 206 </ul> 207 <p>verhindert wurde - denn die Auswertung dieser Regel kann nicht vom Inhalt des empfangenen HTTP-Headers abhängen, so daß in diesem Fällen tatsächlich gar keine Verhandlung <small>(über veränderliche Ereignisse unterschiedlicher HTTP-Requests)</small> statt gefunden hat.</p> 208 <p>Falls jedoch für bestimmte Dateien, von denen aufgrund <em>anderer</em> als dieser beiden Konfigurationsfälle fest steht, daß sie nie in komprimierter Form ausgeliefert werden, keine <code>Vary:</code>-Header gesendet werden sollen, ist es notwendig, für diese Dateien <tt>mod_gzip</tt> <em>abzuschalten</em>.</p> 209 210 </div> 211 212 <div class="new13192a"> 213 214 <p>Ein Beispiel dafür, keine <code>Vary:</code>-Header für GIF-Bilder zu senden, die problemlos innerhalb eines Caches wie Squid 2.4 gespeichert werden dürfen, könnte so aussehen:</p> 215 <pre><FilesMatch \.gif$> 216 mod_gzip_on No 217 <FilesMatch></pre> 218 <p>Für künftige Versionen bleiben derzeit folgende Aufgaben offen:</p> 219 <ul> 220 <li>Die <em>vollständige</em> Erkennung, daß die Reaktion auf die aktuelle Anforderung <em>niemals</em> zur Auslieferung komprimierter Daten führen kann, weil eine <code>mod_gzip_item_exclude</code>-Regel feuert, die nicht von einer Eigenschaft eines Request abhängt.</li> 221 <li>Die Erkennung, daß eine Verhandlung statt gefunden hat, die <em>nicht</em> durch eine Liste von HTTP-Header-Namen beschrieben werden kann - in diesem Fall sollte <code>Vary: *</code> gesendet werden <small>(und die Dokumentation von <tt>mod_gzip</tt> explizit darauf hinweisen, diese Direktiven nur dann zu verwenden, wenn es unbedingt notwendig erscheint, da ihre Gebrauch die Wirkung der Arbeit von Caching Proxies beeinträchtigen wird)</small>.</li> 222 <li>Die Prüfung, ob Konstellationen möglich sind, in denen nur eine Teilmenge der Header-Namen sämtlicher <code>reqheader</code>-Regeln im <code>Vary:</code>-Header benötigt werden - je weniger Namen dort angegeben sind, desto weniger Varianten müssen im Proxy-Cache parallel gespeichert werden.</li> 223 </ul> 224 225 </div> 226 227 <h2><a name="vary-wildcard"></a>Verhandlungen über andere Aspekte als HTTP-Header</h2> 228 <p>In ganz besonderen Fällen, nämlich beim Einsatz bestimmter Konfigurations-Direktiven, findet durch <tt>mod_gzip</tt> eine Verhandlung über Aspekte statt, welche gar nicht durch Namen von HTTP-Headern ausdrückbar sind. Hierzu zählen die Direktiven</p> 229 <ul> 230 <li><a href="config.htm#requirements"><code>mod_gzip_min_http</code></a> <small>(minimal erforderliche HTTP-Version)</small> sowie</li> 231 <li><a href="config.htm#requirements"><code>mod_gzip_handle_methods</code></a> <small>(zu verarbeitende HTTP-Methoden)</small></li> 232 </ul> 233 <p>In beiden Fällen kann <tt>mod_gzip</tt> einem Proxy nicht in Form von Namen von HTTP-Headern erklären, was es getan hat. Die gemäß der <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44"><img class="linkicon" height="15" width="16" alt="arrow" title="external" src="extern.gif" />HTTP/1.1-Spezifikation</a> in diesem Falle angemessene Reaktion ist das Senden des HTTP-Headers <code>Vary: *</code>.</p> 234 235 <div class="new13261a"> 236 237 <p><a href="versions.htm#v1.3.26.1a"><tt>mod_gzip</tt> 1.3.26.1a</a> sendet einen <code>Vary: *</code>-Header, falls die Direktive <code>mod_gzip_min_http</code> verwendet wurde.</p> 238 <p>Bezüglich der Direktive <code>mod_gzip_handle_methods</code> scheint derzeit noch nicht völlig klar zu sein, ob zwei HTTP-Requests nach derselben URI, aber unter Verwendung underschiedlicher HTTP-Methoden, tatsächlich dieselbe HTTP-Informationseinheit anfordern - dies wird darüber entscheiden, ob auch bei der Verwendung dieser Direktive ein <code>Vary: *</code>-Header gesendet werden muß. Mit dieses Problem wird sich eine kommende Version von <tt>mod_gzip</tt> befassen müssen.</p> 239 240 </div> 241 242 <p>Da ein Proxy-Server in diesem Falle aber die Art der durchgeführten Verhandlung nicht verstehen kann, ist er nicht befugt, Antworten mit dieser Angabe in einem Zwischenspeicher aufzubewahren.</p> 243 <p>Auf diese Weise <strong>verhindert die Verwendung einer dieser beiden Direktiven also vollständig die Zwischenspeicherung jeglicher von diesem HTTP-Server ausgelieferten Antworten</strong>, egal ob komprimiert oder nicht. Daher muß von der Verwendung dieser Direktiven inzwischen dringend abgeraten werden.</p> 244 245 <h2><a name="useragent"></a>Der UserAgent als Sonderfall</h2> 246 <p>Die parallele Speicherung von Varianten unterschiedlicher Verhandlungs-Parameter in einem Proxy-Cache mag sinnvoll sein, wenn nur wenige mögliche Werte tatsächlich auftreten können - so wie etwa im Falle von <code>Content-Encoding</code>. Sind jedoch sehr viele verschiedene Werte möglich, dann ist eine parallele Speicherung von Varianten nicht mehr praktikabel.</p> 247 <p>Genau dies trifft auf den <code>UserAgent</code>-Namen als Identifikation des HTTP-Client zu. Jede Sub-Version eines Browsers sendet einen komplexen UserAgent-String, welcher nicht nur Name und Version des Browsers, sondern auch weitere Informationen <small>(Landessprache, Betriebssystem-Name und -Version etc.)</small> enthält. Es gibt hunderte bekannter UserAgent-Strings - und dazu eine Reihe von Mechanismen, diesen UserAgent-String zu verändern. Manche Browser <small>(wie Opera)</small> erlauben dem Anwender sogar, selbst Einfluß auf den Inhalt dieses UserAgent-Strings zu nehmen, um sich für einen anderen Browser auszugeben <small>(weil viele technisch inkompetente Gestalter dynamischer Webseiten ihr Angebot bedingt auf den Namen des Browsers aufbauen und manche Browser dabei unnötigerweise ausschließen, oder auch weil ihr Anwender im Interesse der Wahrung seiner Privatsphäre nicht unnötigerweise Informationen über die von ihm verwendete Computerausrüstung bekannt geben möchte)</small>.</p> 248 <p>Wie sinnvoll in manchen Fällen auch die bedingte Auslieferung komprimierter Webseiten auf die Identität eines HTTP-Clients sein mag <small>(etwa angesichts der zahlreichen Bugs von Netscape 4)</small>, so spricht doch auf jeden Fall gegen die Verwendung des UserAgent-Strings als Grundlage einer HTTP-Verhandlung, daß der Inhalt dieses HTTP-Headers einerseits zu variabel ist, um zuverlässige Schlüsse daraus zu ziehen, und andererseits zu viele verschiedene Werte enthält, als daß ein Zwischenspeicher für all diese Verhandlungs-Varianten parallel die Ergebnisse von Anforderungen für denselben URL aufbewahren kann.</p> 249 250 <div class="new13261a"> 251 252 <p>Seit Version 1.3.19.2a sendet <tt>mod_gzip</tt> einen <code>Vary:</code>-Header, welcher den HTTP-Header <code>User-Agent:</code> als Parameter der Verhandlung bezeichnet, falls eine entsprechende Direktive in der Konfiguration verwendet wurde. Aber die Wahrscheinlichkeit, daß bei einem Folgezugriff ein <em>exakt übereinstimmender</em> <code>User-Agent:</code>-Wert vorliegen wird <small>(so daß dieser Client deshalb den gespeicherten Inhalt erhalten darf)</small> ist sehr niedrig.</p> 253 <p>Zwar <em>würde</em> der HTTP-Server tatsächlich sogar große Mengen von UserAgents <small>(die seiner Konfiguration gemäß als funktionell gleichwertig angesehen werden)</small> während der Verhandlung identisch behandeln - aber der <code>Vary:</code>-Header erlaubt es dem HTTP-Server nicht, dem Zwischenspeicher mitzuteilen, welche Teilbereiche des UserAgent-Strings der HTTP-Server as signifikante Inhalte während der Verhandlung ausgewertet hat. Der Proxy-Server kann lediglich erfahren, <em>daß</em> der UserAgent <em>irgend</em> eine Rolle gespielt hat - und mit diesem Wissen <em>muß</em> der Proxy verschiedene UserAgents als <em>unterschiedlich</em> behandeln, auch wenn der HTTP-Server das vielleicht nicht tun würde.</p> 254 <p><strong>Die Verwendung von Filterregeln mit Auswertung des <code>UserAgent</code>-Headers bewirkt also die vollständige Abschaltung der Zwischenspeicherung für derartig erzeugte Antwortpakete</strong>. Dieses Effekts solte sich ein Anwender von <tt>mod_gzip</tt> unbedingt bewußt sein - und deshalb nach Möglichkeit auf andere Filter-Mechanismen <small>(mit einer geringeren Anzahl unterschiedlicher Werte)</small> zurück greifen, um dieselbe inhaltliche Unterscheidung zwischen diesen HTTP-Clients zu bewirken.</p> 255 256 </div> 257 258 <div id="icon"> 259 <a href="http://validator.w3.org/check/referer"><img alt="" title="valid XHTML 1.1" height="31" width="88" src="valid-xhtml11.png" /></a><a href="http://jigsaw.w3.org/css-validator/check/referer"><img alt="" title="valid CSS" height="31" width="88" src="valid-css.png" /></a> 260 </div> 261 262 263 <p id="mail">(<a href="mailto:michael.schroepl@gmx.de?subject=mod_gzip">Michael Schröpl</a>, 2002-09-30)</p> 264 265 </div> 266 267 </body> 268 </html>