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 beispielsweise int zurück und übernimmt er request_rec * sowie einen int-Wert und wird er mit do_something aufgerufen, 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 DECLINED zurückgibt, stoppt die Schleife und der Rückgabewert wird vom Hook-Aufrufer zurückgegeben. Beachten Sie, dass DECLINED die 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 OK und DECLINED die 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_MIDDLE und HOOK_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_FIRST verwenden, werden selbstverständlich vor Modulen mit HOOK_MIDDLE ausgeführt, die ihrerseits vor HOOK_LAST ausgeführt werden. Module, bei denen es nicht darauf ankommt, wann sie ausgeführt werden, sollten HOOK_MIDDLE benutzen (damit Varianten wie HOOK_FIRST-2 fü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_FIRST und HOOK_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.c und mod_abc.c ausfü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_ORDER gesetzte 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]

Reply via email to