Title: Apache 2.0 Hook-Funktionen
Dokumentation für Entwickler Warnung Dieses Dokument ist noch in Bearbeitung und vielleicht teilweise nicht mehr auf aktuellem Stand.
Im Allgemeinen ist ein Hook eine Funktion, die der Apache an einem bestimmten Punkt während der Verarbeitung einer Anfrage aufruft. Module können Funktionen bereitstellen, die aufgerufen werden und angeben, wann sie im Verhältnis zu anderen Modulen aufgerufen werden.
Eine Hook-Funktion erstellen Um einen neuen Hook einzurichten, müssen Sie vier Schritte durchführen:
Deklaration der Hook-Funktion Benutzen Sie das Makro
AP_DECLARE_HOOK, dem der Rückgabetyp der Hook-Funktion, der Name des Hook und die Argumente übergeben werden. Gibt der Hook beispielsweiseintzurück und übernimmt errequest_rec *sowie einenint-Wert und wird er mitdo_somethingaufgerufen, dann deklarieren Sie ihn wie folgt:AP_DECLARE_HOOK(int, do_something, (request_rec *r, int n)) Das sollte in einem Header stehen, den Module einbinden, wenn sie den Hook benutzen möchten.
Anlegen der Hook-Struktur Jede Quelldatei, die einen Hook exportiert, hat eine private Struktur, in der die Modulfunktionen aufgezeichnet werden, die der Hook benutzt. Sie wird folgendermaßen deklariert:
APR_HOOK_STRUCT(
APR_HOOK_LINK(do_something) )
...
Den Hook-Aufrufer implementieren Die Quelldatei, die den Hook exportiert, muss eine Funktion implementieren, die den Hook aufruft. Zur Zeit kann dies auf drei Arten geschehen. In allen Fällen heißt die aufrufende Funktion
ap_run_hookname().Hooks mit dem Typ void Hat der Rückgabewert eines Hook den Typ
void, dann werden alle Hooks aufgerufen und der Aufrufer wird wie folgt implementiert:AP_IMPLEMENT_HOOK_VOID(do_something, (request_rec *r, int n), (r, n)) Die zweite und dritte Argument sind die Dummy-Argumentdeklaration und die Dummy-Argumente, wie sie beim Hook-Aufruf benutzt werden. Das heißt, dieses Makro wird ungefähr wie folgt expandiert:
void ap_run_do_something(request_rec *r, int n)
{
... }
do_something(r, n);
Hooks mit einem Rückgabewert Liefert der Hook einen Wert zurück, können beide solange ausgeführt werden, bis der erste Hook etwas Interessantes tut, etwa so:
AP_IMPLEMENT_HOOK_RUN_FIRST(int, do_something, (request_rec *r, int n), (r, n), DECLINED) Der erste Hook, der nicht
DECLINEDzurückgibt, stoppt die Schleife und der Rückgabewert wird vom Hook-Aufrufer zurückgegeben. Beachten Sie, dassDECLINEDdie traditionelle Hook-Rückgabe des Apache ist, die soviel bedeutet wie "Ich habe nichts getan", aber sie kann auch etwas anderes bedeuten, wenn Sie das möchten.Alternativ können alle Hooks bis zum Auftreten eines Fehlers ausgeführt werden. Das läuft darauf hinaus, dass zwei Rückgabewerte zugelassen werden, von denen einer bedeutet "Ich habe etwas getan und es war OK" und der andere bedeutet "Ich habe nichts getan". Die erste Funktion, die einen anderen Wert als diese beiden Werte zurückgibt, stoppt die Schleife und ihre Rückkehr ist der Rückgabewert. Deklarieren Sie wie folgt:
AP_IMPLEMENT_HOOK_RUN_ALL(int, do_something, (request_rec *r, int n), (r, n), OK, DECLINED) Es sei noch einmal daraufhingewiesen, dass
OKundDECLINEDdie traditionellen Werte sind. Sie können verwenden, was Sie möchten.Aufruf der Hook-Aufrufer Rufen Sie den Hook-Aufrufer im Code zum entsprechenden Zeitpunkt wie folgt auf:
int n, ret;
request_rec *r;
ret=ap_run_do_something(r, n);Den Hook einklinken Ein Modul, das einen Hook-Aufruf erreichen möchte, muss zwei Dinge tun.
DieHook-Funktion implementieren Binden Sie den entsprechenden Header ein und definieren Sie eine statische Funktion mit dem richtigen Typ:
static int my_something_doer(request_rec *r, int n)
{
... }
return OK;
Eine Hook-Registrierungsfunktion hinzufügen Während der Initialisierung ruft der Apache die in der Modulstruktur befindliche Hook-Registrierungsfunktionfür jedes Moduls auf:
static void my_register_hooks()
{
ap_hook_do_something(my_something_doer, NULL, NULL, HOOK_MIDDLE); }
mode MODULE_VAR_EXPORT my_module =
{
... };
my_register_hooks /* register hooks */
Die Reihenfolge der Hook-Aufrufe steuern Im oben angeführten Beispiel wurden die drei Argumente in der Hook-Registrierungsfunktion, die die Aufrufreihenfolge steuern, nicht benutzt. Dies kann mit zwei Mechanismen geschehen. Bei der ersten, etwas grobe Methode, können Sie ungefähr angeben, wo der Hook im Verhältnis zu anderen Modulen ausgeführt wird. Dies wird mit dem letzten Argument gesteuert. Drei Werte sind möglich:
HOOK_FIRST,HOOK_MIDDLEundHOOK_LAST.Alle Module, die einen bestimmten Wert verwenden, können im Verhältnis zueinander in jeder Reihenfolge ausgeführt werden, aber alle Module, die
HOOK_FIRSTverwenden, werden selbstverständlich vor Modulen mitHOOK_MIDDLEausgeführt, die ihrerseits vorHOOK_LASTausgeführt werden. Module, bei denen es nicht darauf ankommt, wann sie ausgeführt werden, solltenHOOK_MIDDLEbenutzen (damit Varianten wieHOOK_FIRST-2für einen etwas früheren Einstieg möglich sind. Ob das allerdings klug ist, bleibt fraglich. - Ben).Beachten Sie, dass es noch zwei weitere Werte gibt (
HOOK_REALLY_FIRSTundHOOK_REALLY_LAST), die nur vom Hook-Exporteur benutzt werden sollten.Die andere Methode lässt eine feinere Steuerung zu. Wenn ein Modul weiß, dass es vor (oder nach) anderen Modulen ausgeführt werden muss, dann können Sie diese mit Namen angeben. Das zweite (oder dritte) Argument ist ein mit NULL endendes String-Array, das die Namen von Modulen enthält, die vor (oder nach) den aktuellen Modul ausgeführt werden müssen. Möchten Sie beispielsweise die Module
mod_xyz.cundmod_abc.causführen, sieht der Hook folgendermaßen aus:static void register_hooks()
{
static const char * const aszPre[] = { "mod_xyz.c", "mod_abc.c", NULL }; }
ap_hook_do_something(my_something_doer, aszPre, NULL, HOOK_MIDDLE);
Beachten Sie, dass die hierfür verwendete Sortierung stabil ist, so dass die mit
HOOK_ORDERgesetzte Reihenfolge soweit wie möglich beibehalten wird.Ben Laurie, 15. August 1999
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
