编写插件¶
在开始编写自己的插件之前,您应该能够构建 lighttpd (lighttpd 源代码和构建说明),并且应该熟悉 lighttpd 中的基本数据类型和主要头文件
接下来阅读服务器内部结构
查看一些简单的模块,例如 mod_access.c 或 mod_staticfile.c,以了解模块如何工作的基本概念。
骨架¶
编写自己的插件的一个好的起点是随附的 mod_skeleton.c,它只包含一个基本骨架。要将 mod_skeleton 转换为有用的插件,请使用您喜欢的编辑器并将所有出现的“skeleton”替换为您的插件名称
$ cd src/ $ cp mod_skeleton.c mod_counter.c $ vi mod_counter.c :%s/skeleton/counter/g
并在
src/Makefile.am
中添加一些行,以告知构建系统您的新插件lib_LTLIBRARIES += mod_counter.la mod_counter_la_SOURCES = mod_counter.c mod_counter_la_LDFLAGS = $(common_module_ldflags) mod_counter_la_LIBADD = $(common_libadd)
调用
make
,如果一切顺利,src/mod_counter.la
和 src/mod_counter.lo
文件将位于您的构建目录中,并且模块将链接到 src/.libs/mod_counter.so
中
旁注:在开发过程中,您可能会选择使用替代的路径前缀来安装所有文件,因为您不想干扰真实的安装。
$ ./configure --prefix=${HOME}/testbed/lighttpd-1.4.x/ ...
这也可以免去以 root 身份安装所有文件的负担。只需更改您的配置以使用大于 1024 的端口,运行 lighttpd 就不再需要 root 权限。
(lighttpd 源代码和构建说明)
代码布局¶
现在看看您的插件 mod_counter。您应该会看到
- 配置结构:plugin_config 和 plugin_data
- 结构的初始化代码
- set_defaults 用于解析配置
- 应用条件判断的 patch-函数
- 实际工作代码,最后是
- plugin_init 函数,该函数在插件注册到服务器后被调用一次
plugin_config¶
每个插件都可以选择处理来自全局配置文件的条件判断,并将不同的设置存储在一个按条件区分的 plugin_config 中。这个结构体链接在下一个插件范围的结构体:plugin_data 中。
plugin_data¶
每个插件都有一些只属于该插件的本地数据(例如配置和一些临时缓冲区)。
handler_ctx¶
如果插件必须存储连接特定的信息,您需要另一个结构体,其中每个连接都有一个条目。以 mod_rewrite 为例。
模板函数¶
- _init
- _free
- _set_defaults
- _plugin_init
_plugin_init¶
每个插件都必须有一个 ..._plugin_init 函数,该函数在插件被调用时被调用。它应该只将 p->name 设置为一个包含插件名称(人类可读)的缓冲区,并填充钩子(init, set_defaults, cleanup),然后返回 0。
_init¶
..._init 函数用于初始化插件本身,并返回带有有用默认值的 plugin_data 结构体。
_free¶
..._free 在插件生命周期结束时被调用,用于指示插件释放所有已分配的内存。请记住,最好不要让程序终止为您清理内存。释放您所有 malloc 的内容。使用 valgrind 或其他工具验证您的工作。
_set_defaults¶
一旦配置文件被解析,每个插件都有机会从配置中获取其配置值并在内部进行验证。config_plugin_keys_t 结构体包含配置键和您期望的类型。不要忘记结构体的最后一个条目应包含一个 NULL 名称以标记结束。
如果您不关心条件判断,set_defaults 函数非常简单
- 设置 config_plugin_keys_t 的目标
- 调用 config_plugin_values_init()
条件判断¶
patch 函数设置基本默认值并应用当前有效条件所需的修改。
在使用时,不要忘记检查修补后的配置是否有意义。
一旦调用了工作处理程序(例如 _uri_handler 及相关函数),就必须调用 patch 函数。
mod_counter_patch_config(r, p);
返回值¶
在大多数情况下,您只会使用 HANDLER_GO_ON、HANDLER_FINISHED 和 HANDLER_ERROR。
HANDLER_GO_ON 在大多数情况下返回,当您希望其他插件也有机会处理请求时。如果您知道此请求与您无关,只需返回 HANDLER_GO_ON 即可完成。
HANDLER_ERROR 应该只在发生致命错误时调用,因为它如果在某个处理程序中调用,将终止当前连接;如果在 _set_defaults 中调用,则终止 lighttpd。
HANDLER_FINISHED 是最终的返回码,用于指示一切都已准备好服务请求,例如
- HTTP 状态码
r->http_status = xxx
已设置 - 内容已生成,并且
r->resp_body_finished = 1
已设置
HANDLER_WAIT_FOR_EVENT 和 HANDLER_WAIT_FOR_FD 应该在您尚未完成且必须等待 fd 事件或 fd 不足时返回。
HANDLER_COMEBACK 在您希望重新检查请求结构时很有用。这在 mod_rewrite 中用于处理重写后的 URI。