项目

通用

个人资料

操作

编写插件

在开始编写自己的插件之前,您应该能够构建 lighttpd (lighttpd 源代码和构建说明),并且应该熟悉 lighttpd 中的基本数据类型和主要头文件

接下来阅读服务器内部结构

查看一些简单的模块,例如 mod_access.cmod_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.lasrc/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。

gstrauss 2 年多前更新 · 23 次修订