如何编写lighttpd插件

来源:互联网 发布:js注册登录页面验证 编辑:程序博客网 时间:2024/06/07 02:10
分类: lighttpd 1096人阅读评论(0)收藏举报
编写插件
在开始编写插件之前,应该先熟悉lighttpd中两个基本数据结构以及他们所在文件:
  • buffer (buffer.c)
  • array (array.c)
  • global structures (base.h)
接下来需要阅读:
  • http://www.lighttpd.net/documentation/state.html (lighttpd的'doc/'目录下可以找到,名字为state.txt)
  • http://www.lighttpd.net/documentation/plugins.html (lighttod的'doc/'目录下可以找到,名字为plugins.txt)
框架
确保你的系统中安装
  • automake 1.8.x or higher
  • autoconf 2.57 or higher
  • libtool 1.5.x or higher 
当要编写自己的插件,可以从修改mod_skeleton.c开始,mod_skeleton.c包括一个插件的基本架构,它是mod_access模块的一个拷贝,mod_access模块非常简单,以至于把mod_access模块作为演示插件如何工作的基本向导。

如何把mod_skeleton变成一个自己的插件,你需要用编辑器打开这个文件,把文件里面的 'skeleton'替换成你自己的插件名‘counter’。

$ 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 = -module -export-dynamic -avoid-version -no-undefined

mod_counter_la_LIBADD = $(common_libadd)
默认情况下,生成系统将假定你是一个普通用户,只是想编译现有代码。所以更改makefile.am文件后不会产生新的makefiles 。你需要手工执行以下命令:
$ ./configure --enable-maintainer-mode ...
无论何时更新Makefile.am,比如增加新的依赖库,执行上面命令都会自动重建完整的Makefile文件.
开发过程中,如果你希望通过前缀安装所有的文件来避免真实安装,可以:

$ ./configure --enable-maintainer-mode --prefix=${HOME}/testbed/lighttpd-1.4.x/ ...

这样可以消除你每次以root身份安装的负担,并且不需要root权限就可以运行lighttpd。启动lighttpd之前,最好把lighttpd配置文件中的port修改为大于1024的端口。
如果开发的插件不能正常工作,您可能需要使用autoconf重新创建生成系统,如下命令
$autoreconf -fi
$./configure --enable-maintainer-mode ...
如果一切正确, 生成目录中将会创建mod_counter.la 和 mod_counter.lo两个文件 .
调整代码

查看mod_counter插件. 你会发现:

  • 配置结构体: plugin_config和plugin_data。
  • 结构体初始化代码。
  • set_defaults函数分析配置结构。
  • the patch-function which applies the conditionals
  • the real work code and finally
  • plugin_init函数在插件注册服务时被调用一次。
plugin_config
每个插件在全局配置文件中可以选择是否设置配置信息,并且可以通过plugin_config结构体记录这些不同的设置信息。这个结构体被用在结构体plugin_data结构中,用于保存插件的配置信息。
plugin_data
每个插件都有属于插件自身的本地数据(像配置信息和临时缓存),通过plugin_data结构体保存这些数据。
handler_ctx
如果插件需要存储此次连接(connection)的特定信息,需要用handler_ctx结构来存储每个连接的信息。更深入的了解可以参考mod_rewrite插件。
所需函数
  • _init
  • _free
  • _set_defaults
  • _plugin_init
_plugin_init
每个插件需要编写 ..._plugin_init函数,这个函数会在插件加载时被调用。需要设置p->name指向插件名字(用户定义的插件名,本例中为counter)缓存地址,设置相关的钩子(hooks)函数(init,set_defaults,cleanup),最后返回0即可。
_init
..._init函数在插件自身初始化时被调用,这个函数返回plugin_data结构体指针。
_free
..._free 函数在插件生命期要结束时被调用,这个函数用来释放插件申请的内存,记住不要让程序结束时为你清理内存,请自己手动释放插件中申请的内存。考虑使用valgrind或者其他工具分析验证你写的插件是否存在问题。
_set_defaults
一旦配置文件被解析,每个插件都有机会从配置文件中获取它的配置值,并验证正确性,在插件中使用config_values_t结构体保存配置文件中相应的关键字和类型信息。需要注意的是Config_values_t结构体的最后一项必须用NULL标示结束。
如果你不关心插件配置, set_defaults功能是相当简单的:
  • set the destinations of the config_values_t
  • 调用config_insert_values_global()
conditionals
如果编写的插件需要配置信息,在调用config_insert_values_global()函数之前还需要多做一些工作(就是对配置文件内容的解析处理),具体参考mod_access.c模块中的实现。
使用config_storage存储所有的条件和一个patch函数(比如mod_counter_patch_connection函数)。

patch function sets the basic defaults and applies the necessary modifications for the currently valid conditionals.

Don't forget to check if the patched config makes sense when you use it.

The patch functions have to be called as soon as one of the work-handlers is called (like _uri_handler and friends).

        mod_counter_patch_connection(srv, con, p);

插件返回值
在大多数情况下,只需要使用HANDLER_GO_ON, HANDLER_FINISHED and HANDLER_ERROR作为插件的返回值。
HANDLER_GO_ON:当你需要其他插件处理此次请求时,在多数情况下返回HANDLER_GO_ON。有时如果你知道不需要处理这个请求,可以直接返回HANDLER_GO_ON。
HANDLER_ERROR:当发生致命错误时,当连接终止时,当调用hanlers相关函数(产生错误时)或者终止lighttpd时,当调用_set_defaults函数时(主要指配置文件出错时)返回HANDLER_ERROR。
HANDLER_FINISHED: 终止返回值状态,在以下两种情况下返回:
  • 设置非200的状态码;
  • 生成完用户所需的内容;
HANDLER_WAIT_FOR_EVENT 和 HANDLER_WAIT_FOR_FD:当插件没有处理完成并等待fd-event或者执行FDs时,需要返回HANDLER_WAIT_FOR_EVENT或者HANDLER_WAIT_FOR_FD(这两种状态码用在异步事件处理的插件中,比如mod_proxy,mod_fastcgi等插件中,以后还会提到)
HANDLER_COMEBACK:当需要重新检查请求结构(request-structur)时,需要返回HANDLER_COMEBACK状态码。在mod_rewrite插件中用于重写URI.
翻译原文:
http://trac.lighttpd.net/trac/wiki/HowToWriteALighttpdPlugin
说明:在这片文章的原文中作者没有严格区分plugin(插件)和module(模块)的概念,这里为了和原文一致,在出现plugin的地方翻译为插件,出现module的地方翻译为模块,两者表示相同的意思。对于patch-function部分,实在不好翻译,所以没有翻译,好在这部分内容容易理解。
初次翻译,有不合适的地方,欢迎大家批评指正。也希望和大家对lighttpd相关内容进行探讨。
本文版权归原文所有,转载请注明出处