閱讀570 返回首頁    go 技術社區[雲棲]


如何編寫lighttpd插件

編寫插件
在開始編寫插件之前,應該先熟悉lighttpd中兩個基本數據結構以及他們所在文件:
接下來需要閱讀:
框架
確保你的係統中安裝
  • 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.
翻譯原文:
https://trac.lighttpd.net/trac/wiki/HowToWriteALighttpdPlugin
說明:在這片文章的原文中作者沒有嚴格區分plugin(插件)和module(模塊)的概念,這裏為了和原文一致,在出現plugin的地方翻譯為插件,出現module的地方翻譯為模塊,兩者表示相同的意思。對於patch-function部分,實在不好翻譯,所以沒有翻譯,好在這部分內容容易理解。
初次翻譯,有不合適的地方,歡迎大家批評指正。也希望和大家對lighttpd相關內容進行探討。
本文版權歸原文所有,轉載請注明出處!

最後更新:2017-04-02 00:06:29

  上一篇:go 利用 Spring 與 Log4J 巧妙地進行動態日誌配置切換並立即生效
  下一篇:go [原創]另類調用 printf 完成任務的方法