该文档仍在开发中,可能已过时。
通常,挂钩函数是Apache HTTP Server在处理请求期间的某个时刻将调用的函数。模块可以提供被调用的函数,并指定与其他模块相比它们何时被调用。
httpd的核心模块提供了在标准请求处理
阶段使用的挂钩的预定义列表。创建一个新的钩子将公开一个实现它的函数(请参阅以下部分),但必须了解您不会扩展httpd的核心钩子,这一点很重要。它们在请求处理中的存在和顺序实际上是调用它们的方式的结果server/request.c
(请查看此部分
以获取概述)。核心挂钩在doxygen文档中列出
。
为了创建一个新的钩子,需要完成四件事:
使用AP_DECLARE_HOOK
宏,需要为其提供钩子函数的返回类型,钩子的名称和参数。例如,如果该钩子返回an int
并接受a request_rec *
和an 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_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); }
请注意,用于实现此目的的排序是稳定的,因此将尽可能保留by的排序。APR_HOOK_ORDER
可用语言: zh