apache 模組編寫(c++)
注:
路徑為:/home/xxx/
工具為:apxs
框架搭建:
1、準備工作:安裝apache對應的httpd-devel,主要是為了安裝apxs。
2、生成一個apache的模組框架:cd /home/xxx/; apache module:apxs -g -n mytest
這裡的mytest就是apache模組的名字,但是實際生成的so名為:mod_mytest.so
3、編譯apache模組:使用c++語言編寫apache模組,網上有說使用extern"C"的方法(見http://hi.baidu.com/zhangsilly/blog/item/a43fa11f869f4efae1fe0bf3.html),但是沒有實驗成功。extern"C"會有警告,而且編譯不過~!
最後,將我的所有後臺處理程式做成了一個liblogic.so,然後apache的模組mytest載入這個liblogic.so,而apache模組mytest中只是接收請求,傳遞引數給liblogic.so進行處理!而在mytest的模組編譯時,使用apxs的引數-S進行CC重新命名,如下:
apxs -c -a -S CC=g++ -I./src -I./src/common/ -llogic -L./src/ mod_mytest.c -Wl,-rpath=/home/xxx/mytest/src/
這裡需要注意,即使你的mod_mytest.c中使用c++語言來編寫,但是這個檔案不能使用mod_mytest.cpp來進行命名,必須使用.c的字尾,否則不能編譯!具體原因不明,待查!在使用-Wl,-rpath的時候,應用程式對實際的動態庫路徑尋找,需要注意!
可以通過/usr/lib64/apr-1/build/libtool --silent --mode=link g++ ...... 這裡的silent去掉,看到具體的編譯命令,前面有-Wl,--rpath -Wl,...可以看看!~
編譯連結成功以後,在.libs/下會生成我們所用的mod_mytest.so
4、修改httpd.conf,新增:
LoadModule mytest_module /home/xxx/mytest/.libs/mod_mytest.so
<Location /index>
SetHandler mytest
</Location>
這裡的index,表示index所對應的請求,比如:http://www.baidu.com/index?a=1&b=2 --- 這裡的index將會使用module mytest去處理@!
apache模組的開發
經常會看的一個頭檔案:/usr/include/httpd/httpd.h
我們需要從哪兒入手:
開啟mod_mytest.c檔案,找到:static int mytest_handler(request_rec *r)這行!
這個函式就是我們需要修改的函式!
這裡需要指出,對於所有的請求資訊,都在這個r引數裡!
第一個問題:取得url中的引數
http://www.baidu.com/index?a=1&b=2 比如,要取得上面的a/b兩個引數,如何搞? 答案在r->args裡,如上的url,r->args="a=1&b=2",我們所要做的事情是從這個串裡取得a=1/b=2 下面是我寫的一個函式,用來得到引數的,僅供參考!- char* get_args_param(request_rec* r, constchar* name)
- {/*{{{*/
- constchar* args = r->args;
- constchar* start_args;
- if (NULL != args)
- {
- for (start_args = ap_strstr_c(args, name); start_args;
- start_args = ap_strstr_c(start_args + 1, name))
- {
- if (start_args == args || start_args[-1] == '&' || isspace(start_args[-1]))
- {
- start_args += strlen(name);
- while (*start_args && isspace(*start_args))
- ++start_args;
- if (*start_args == '=' && start_args[1])
- {
- char* end_args;
- char* arg;
- ++start_args;
- arg = apr_pstrdup(r->pool, start_args);
- if ((end_args = strchr(arg, '&')) != NULL)
- *end_args = '/0';
- return arg;
- }
- }
- }
- }
- return NULL;
- }/*}}}*/
第二個問題:如何得到特定的cookie
這裡需要用到r->headers_in,這是一個apr_table_t型別的hashmap!下面會詳細說下。 因為cookie是類似於:abc=ui230jklsiu;def=uiore0832jhh1;這樣的 這裡就要使用到我上面所說的apache中proxy模組的原始碼: apache-2.2.11-src/modules/proxy/mod_proxy_balancer.c中有get_cookie_param函式! 去看吧,google吧!- char *get_cookie_param(request_rec *r, constchar *name)
- {/*{{{*/
- constchar *cookies;
- constchar *start_cookie;
- if ((cookies = apr_table_get(r->headers_in, "Cookie"))) {
- for (start_cookie = ap_strstr_c(cookies, name); start_cookie;
- start_cookie = ap_strstr_c(start_cookie + 1, name)) {
- if (start_cookie == cookies ||
- start_cookie[-1] == ';' ||
- start_cookie[-1] == ',' ||
- isspace(start_cookie[-1])) {
- start_cookie += strlen(name);
- while(*start_cookie && isspace(*start_cookie))
- ++start_cookie;
- if (*start_cookie == '=' && start_cookie[1]) {
- char *end_cookie, *cookie;
- ++start_cookie;
- cookie = apr_pstrdup(r->pool, start_cookie);
- if ((end_cookie = strchr(cookie, ';')) != NULL)
- *end_cookie = '/0';
- if((end_cookie = strchr(cookie, ',')) != NULL)
- *end_cookie = '/0';
- return cookie;
- }
- }
- }
- }
- return NULL;
- }/*}}}*/
第三個問題:如何取得ip
r->connection->remote_ip 不多說了!第四個問題:如何輸出:
apache 提供了很多的輸出函式,都是使用ap_打頭的,在/usr/include/httpd/http_protocol.h中可以看到。下面摘錄幾個:
AP_DECLARE(int) ap_rputc(int c, request_rec *r);
AP_DECLARE(int) ap_rputs(const char *str, request_rec *r);
AP_DECLARE(int) ap_rwrite(const void *buf, int nbyte, request_rec *r);
AP_DECLARE_NONSTD(int) ap_rvputs(request_rec *r,...);
AP_DECLARE(int) ap_vrprintf(request_rec *r, const char *fmt, va_list vlist);
……
需要注意,對於ap_rputs,str不可為NULL,否則會引起core!
參考:
還有更多的說明,可以參考標頭檔案:/usr/include/httpd/httpd.h
或者下面的網址對你有幫助:
對apache的一些常見問題說明:http://blog.sina.com.cn/s/blog_5bf18faf0100aph8.html
一個helloworld的例子:http://andrew913.javaeye.com/blog/398648
reqeust_rec的結構說明:http://hi.baidu.com/start_and_end/blog/item/f344224ecadcc9c1d0c86a79.html
server_rec的結構說明:http://book.51cto.com/art/200805/72067.htm
apxs工具簡介:http://lamp.linux.gov.cn/Apache/ApacheMenu/programs/apxs.html
關於filter模組的一個例項:http://www.cnblogs.com/ithurricane/archive/2009/01/01/1366312.html
後續補充:
1.對於apache的輸出壓縮需要考慮(使用mod_deflate.so),可以參考http://www.bestchao.net/archives/134
比較重要的一段:
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
</IfModule>