Title: Wie Filter unter Apache 2.0 funktionieren
Dokumentation für Entwickler Achtung Dieses Dokument wurde mit "Ausschneiden und Einfügen" aus einer E-Mail (<[EMAIL PROTECTED]>) erstellt und damit es besser lesbar ist, neu formatiert. Es ist nicht auf aktuellem Stand, kann aber als Ausgangspunkt für weitere Untersuchungen dienen.
Filtertypen Es gibt drei Grundtypen von Filtern (die sich jeweils in zwei Kategorien unterteilen lassen, worauf später noch eingegangen wird).
CONNECTION- Filter diesen Typs sind für die Dauer dieser Verbindung gültig. (
AP_FTYPE_CONNECTION,AP_FTYPE_NETWORK)PROTOCOL- Filter diesen Typs sind für die Dauer dieser Anfrage aus der Sicht des Client gültig, was bedeutet, dass die Anfrage vom Versenden bis zum Eingang der Antwort gültig ist. (
AP_FTYPE_PROTOCOL,AP_FTYPE_TRANSCODE)RESOURCE- Filter diesen Typs sind für die Zeit gültig, in der dieser Inhalt für eine Anfrage verwendet wird. Bei einfachen Anfragen ist dies identisch mit dem Filter
PROTOCOL, aber interne Umleitungen und Unteranfragen können den Inhalt verändern, ohne dass die Anfrage damit beendet ist. (AP_FTYPE_RESOURCE,AP_FTYPE_CONTENT_SET)Die Unterscheidung zwischen einem Protokoll und einem Ressourcenfilter ist von Bedeutung. Ein Ressourcenfilter ist an eine bestimmte Ressource gebunden, er kann auch an Header-Informationen gebunden sein, die wichtige Bindung ist jedoch die an die Ressource. Wenn Sie einen Filter erstellen und wissen wollen, ob es sich um eine Ressource oder um ein Protokoll handelt, dann lautet die richtige Frage: "Kann dieser Filter verschoben werden, wenn die Anfrage zu einer anderen Ressource umgeleitet wird?" Lautet die Antwort "Ja", dann handelt es sich um einen Ressourcenfilter. Lautet sie "Nein", handelt es sich wahrscheinlich um ein Protokoll oder um einen Verbindungsfilter. Auf Verbindungsfilter wird hier nicht eingegangen, weil sie hinreichend verständlich sind. Die Definitionen können mit einigen Beispielen verdeutlicht werden:
- byterange
- Dieser Filter wurde so kodiert, dass er für alle Anfragen eingefügt und entfernt werden kann, wenn er nicht verwendet wird. Da dieser Filter zu Beginn aller Anfragen aktiv ist, kann er bei einer Umleitung nicht entfernt werden, dementsprechend handelt es sich um einen Protokollfilter.
- http_header
- Dieser Filter schreibt eigentlich die Header für das Netzwerk. Er wird offensichtlich benötigt (außer im Sonderfall von
mod_asis , worauf weiter unten noch eingegangen wird) und er ist somit ein Protokollfilter.- deflate
- Der Administrator konfiguriert diesen Filter entsprechend der angeforderten Datei. Bei einer internen Umleitung von einer Autoindex-Seite zu einer
index.html- Seite kann derdeflate-Filter entsprechend der Konfiguration hinzugefügt oder entfernt werden, daher handelt es sich um einen Ressourcenfilter.Die weitere Unterteilung der einzelnen Kategorien in zwei weitere Filtertypen dient ausschließlich der Anordnung. Wir könnten sie aufheben und nur einen Filtertyp zulassen, dann würde aber die Anordnung durcheinander geraten und es wären Eingriffe notwendig, um die Funktion zu gewährleisten. Zur Zeit besitzen die
RESOURCE-Filter nur einen Filtertyp, aber das sollte geändert werden.Wie werden Filter eingefügt? In der Theorie ist das eigentlich ganz einfach, der Code ist jedoch kompliziert. Zuerst einmal ist es wichtig, dass jeder sich klar macht, dass es drei Filterlisten für jede Anfrage gibt, die aber alle miteinander verkettet sind. Die erste Liste sind
r->output_filters, dann folgenr->proto_output_filtersund anschließendr->connection->output_filters. Sie entsprechen denRESOURCE-,PROTOCOL- undCONNECTION-Filtern. Vorher bestand das Problem darin, dass eine einfach verknüpfte Liste benutzt wurde, um einen Filter-Stack zu erzeugen. Begonnen wurde dabei mit der "korrekten" Position. War eineRESOURCE-Filter im Stack und einCONNECTION-Filter wurde hinzugefügt, dann bedeutete das, dass derCONNECTION-Filter ignoriert wird. Das erscheint sinnvoll, weil der Verbindungsfilter am Anfang derc->output_filters-Liste eingefügt wird, während das Ende vonr->output_filtersauf den Filter zeigt, der normalerweise am Beginn vonc->output_filtersstand. Das ist offensichtlich falsch. Der neue Code für das Einfügen benutzt eine doppelt verknüpfte Liste. Das hat den Vorteil, dass ein eingefügter Filter niemals verloren geht. Leider gibt es noch anderes Problem.Es besteht darin, dass es zwei unterschiedliche Fälle gibt, in den wir Unteranfragen verwenden. Im ersten Fall werden weitere Daten in eine Antwort eingefügt. Im zweiten wird die vorhandene Antwort durch eine interne Umleitung ersetzt. Dies sind zwei unterschiedliche Situationen, die entsprechend behandelt werden müssen.
Im ersten Fall erzeugen wir die Unteranfrage aus einem Handler oder Filter heraus. Das bedeutet, dass der nächste Filter an die Funktion
make_sub_requestweitergereicht werden sollte und dass der letzte Ressourcenfilter der Unteranfrage auf den nächsten Filter der Hauptanfrage verweist. Das ist sinnvoll, wenn die Daten der Unteranfrage durch die gleichen Filter laufen müssen wie die Hauptanfrage. Eine grafische Darstellung kann das verdeutlichen: Default_handler --> includes_filter --> byterange --> ...Erzeugt der
include_filtereine Unteranfrage, dann sollen die Daten dieser Unteranfrage durch diesen Filter laufen, weil es sich nicht um SSI-Daten handeln kann. Daher nimmt die Unteranfrage folgende Ergänzung vor:Default_handler --> includes_filter -/-> byterange --> ... / Default_handler --> sub_request_coreWas geschieht, wenn die Unteranfrage SSI-Daten enthält? Das ist ganz einfach, der
includes_filterist ein Ressourcenfilter, daher wird er der Unteranfrage zwischen demDefault_handlerund demsub_request_core-Filter hinzugefügt.Der zweite Fall für Unteranfragen liegt vor, wenn eine Unteranfrage zu einer richtigen Anfrage wird. Das geschieht immer dann, wenn eine Unteranfrage außerhalb eines Handler oder Filters erzeugt wird und NULL als nächster Filter an die Funktion
make_sub_requestweitergegeben wird.In diesem Fall sind die Ressourcenfilter nicht mehr sinnvoll, weil sich die Ressource geändert hat. Anstatt ganz von vorne zu beginnen, wird einfach auf den Anfang der Ressourcenfilter für die Unteranfrage am Anfang der Protokollfilter für die alte Anfrage verwiesen. Das bedeutet, dass keine Protokollfilter verloren gehen und die Daten auch nicht durch einen Filter geleitet werden, der nicht für sie vorgesehen ist.
Das Problem ist, dass jetzt eine doppelt verknüpfte Liste für die Filter-Stacks benutzt wird. Sie sollten aber beachten, dass es möglich ist, bei zwei Listen dieses Modell zu durchkreuzen. Wie wird mit dem vorherigen Filter umgegangen? Diese Frage ist schwer zu beantworten, weil es keine "richtige" Antwort noch eine gleichermaßen gültige Methode gibt. Ich habe untersucht, warum der Pointer verwendet wird. Der einzige Grund ist, dass Hinzufügen neuer Server zu vereinfachen. Vor diesem Hintergrund habe ich die Lösung gewählt, den vorherigen Pointer immer auf die ursprüngliche Anfrage verweisen zu lassen.
Das führt zu einer etwas komplexeren Logik, funktioniert aber in allen Fällen. Meine Bedenken hinsichtlich der Verschiebung auf die Unteranfrage rühren daher, dass in den allgemeineren Fällen (wo einer Antwort mit der Unteranfrage Daten hinzugefügt werden), die Hauptfilterkette falsch wäre. Das scheint mir keine gute Idee zu sein.
Asis Der letzte Punkt. :-)
mod_asishat etwas von einem Hack, aber der Handler muss alle Filter mit Ausnahme des Verbindungsfilters entfernen und die Daten senden. Wenn Siemod_asis benutzen, sind alle anderen außer Kraft gesetzt.Erläuterungen Zum Abschluss sei erwähnt, dass der Grund, warum dieser Code so schwer zu formulieren war, die Tatsache war, dass er so stark manipuliert werden musste, damit er funktioniert. Die meisten der Manipulationen habe ich selbst vorgenommen, so dass die Schuld bei mir liegt. Aber jetzt, wo der Code richtig ist, habe ich damit begonnen, einige Hacks zu entfernen. Den meisten sollte aufgefallen seien, dass die Funktionen
reset_filtersundadd_required_filtersverschwunden sind. Diese haben auf Protokollebene Filter für Fehlerbedingungen eingefügt und seltsamer Weise haben beide Funktionen nacheinander das Gleiche getan. Da jetzt keine Protokollfilter für Fehlersituationen mehr verloren gehen, sind diese Hacks entfernt worden. Die FilterHTTP_HEADER,content-lengthundbyterangewurden in dieinsert_filters-Phase eingefügt, denn würden sie vorher eingefügt, dann käme es zu interessanten Interaktionen. Sie konnten jetzt alle so verschoben werden, dass sie mit den FilternHTTP_IN,COREundCORE_INeingefügt werden. Auf diese Weise ist der Code leichter nachzuvollziehen.--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
