Apache HTTP 伺服器版本 2.4
可用語言: en
本文件仍在開發中,且部分內容可能已過時。
一般而言,鉤子函式是 Apache HTTP Server 在處理要求時,在某些時間點會呼叫的函數。模組可以提供會被呼叫的函式,並指定相較於其他模組時,什麼時候會呼叫該函式。
httpd 的核心模組提供了一個預先定義的鉤子清單,用於標準 要求處理 階段。建立新的鉤子會公開一個實作該鉤子的函式(請參閱下方的區段),但務必了解您不會延伸 httpd 的核心鉤子。它們在要求處理中的存在和順序,實際上是根據它們在 server/request.c
中被呼叫的方式而定(請查看 本區段 以取得概觀)。核心鉤子列於 doxygen 文件 中。
若要建立新的鉤子,需要執行四件事
使用 AP_DECLARE_HOOK
巨集,需要給它鉤子函式的回傳類型、鉤子的名稱和引數。例如,如果鉤子回傳一個 int
,並需要一個 request_rec *
和一個 int
,並稱為 do_something
,則要像這樣宣告
AP_DECLARE_HOOK(int, do_something, (request_rec *r, int n))
這應該在標頭中,如果模組想要使用該鉤子,就會包含在其中。
每個匯出鉤子的原始碼檔案都有私有結構,用於記錄使用該鉤子的模組函式。這是宣告的方式
APR_HOOK_STRUCT( APR_HOOK_LINK(do_something) ... )
匯出鉤子的原始碼檔案必須實作一個會呼叫鉤子的函式。目前有三個可行的方法。在所有情況下,呼叫函式都稱為 ap_run_hookname()
。
如果掛勾的回傳值為 void
,則會呼叫所有掛勾,且呼叫者實作如下
AP_IMPLEMENT_HOOK_VOID(do_something, (request_rec *r, int n), (r, n))
第二個與第三個引數是偽變數宣告與偽引數,將於呼叫掛勾時使用。換句話說,此巨集展開成如下內容
void ap_run_do_something(request_rec *r, int n) { ... do_something(r, n); }
如果掛勾傳回值,則可執行以下動作,直到第一個進行某項有趣操作的掛勾
AP_IMPLEMENT_HOOK_RUN_FIRST(int, do_something, (request_rec *r, int n), (r, n), DECLINED)
不傳回 DECLINED
的第一個掛勾,會停止迴圈,且其回傳值會從掛勾呼叫者傳回。請注意,DECLINED
是傳統的掛勾回傳值,意指「我沒做任何動作」,但實際上可依需求設定。
或者,可以在發生錯誤前執行所有掛勾。這歸結為允許兩個回傳值,其中一個意謂「我做了某件事,而且沒問題」,另一個意謂「我沒做任何動作」。傳回上述兩個以外值的函式,會停止迴圈且其回傳值會成為回傳值。宣告如下
AP_IMPLEMENT_HOOK_RUN_ALL(int, do_something, (request_rec *r, int n), (r, n), OK, DECLINED)
再次重申,OK
和 DECLINED
是傳統值。您可以依需求使用。
於程式碼中的適當時機呼叫掛勾呼叫者,如下所示
int n, ret; request_rec *r; ret=ap_run_do_something(r, n);
想要呼叫掛勾的模組需要執行兩件事。
包含適當的標頭,並定義正確類型的靜態函式
static int my_something_doer(request_rec *r, int n) { ... return OK; }
於初始化期間,伺服器會呼叫每個模組的掛勾註冊函式,其中包含在模組結構中
static void my_register_hooks() { ap_hook_do_something(my_something_doer, NULL, NULL, APR_HOOK_MIDDLE); } mode MODULE_VAR_EXPORT my_module = { ... my_register_hooks /* register hooks */ };
於上述範例中,我們沒有在掛勾註冊函式中使用控制所有在掛勾中註冊函式呼叫順序的三個引數。有兩種可執行這個動作的機制。第一種相當粗糙的方法,允許我們指定掛勾的執行位置與其他模組的相對關係。最後一個引數控制這項設定。共有三個可能值:APR_HOOK_FIRST
、APR_HOOK_MIDDLE
和 APR_HOOK_LAST
。
使用任何特定值的所有模組,可能會以任意順序彼此執行,但當然地,使用 APR_HOOK_FIRST
的所有模組,會在 APR_HOOK_MIDDLE
執行之前執行,而 APR_HOOK_MIDDLE
會在 APR_HOOK_LAST
執行之前。不在乎執行時機的模組,應該使用 APR_HOOK_MIDDLE
。這些值是分散的,因此可將位置設定為 APR_HOOK_FIRST-2
,以讓掛勾略早於其他函式執行。
請注意另外還有兩個值,APR_HOOK_REALLY_FIRST
和 APR_HOOK_REALLY_LAST
。這些值只能由掛勾輸出者使用。
另一種方法允許更精準的控制。當模組知道它必須在其他模組之前(或之後)執行時,它可以透過名稱來指定它們。第二個(或第三個)參數是一個由字串組成的 NULL 終止陣列,其中包含必須在目前模組之前(或之後)執行的模組名稱。例如,假設我們想要在執行動作之前執行「mod_xyz.c」和「mod_abc.c」,那麼我們可以照以下方式掛鈎
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, APR_HOOK_MIDDLE); }
請注意,用於達成這項操作的排序是穩定的,因此透過 APR_HOOK_ORDER
設定的排序將會被保留下來,只要有可能。
可用語言: en