1. 通過apxs生成
1.1 簡單版
使用apxs -n helloworld -g
可生成helloworld模塊:
renz@apache1:~/helloworld$ ls
Makefile mod_helloworld.c modules.mk
生成mod_helloworld.c代碼如下:
/*
** mod_helloworld.c -- Apache sample helloworld module
** [Autogenerated via ``apxs -n helloworld -g'']
**
** To play with this sample module first compile it into a
** DSO file and install it into Apache's modules directory
** by running:
**
** $ apxs -c -i mod_helloworld.c
**
** Then activate it in Apache's apache2.conf file for instance
** for the URL /helloworld in as follows:
**
** # apache2.conf
** LoadModule helloworld_module modules/mod_helloworld.so
** <Location /helloworld>
** SetHandler helloworld
** </Location>
**
** Then after restarting Apache via
**
** $ apachectl restart
**
** you immediately can request the URL /helloworld and watch for the
** output of this module. This can be achieved for instance via:
**
** $ lynx -mime_header http://localhost/helloworld
**
** The output should be similar to the following one:
**
** HTTP/1.1 200 OK
** Date: Tue, 31 Mar 1998 14:42:22 GMT
** Server: Apache/1.3.4 (Unix)
** Connection: close
** Content-Type: text/html
**
** The sample page from mod_helloworld.c
*/
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
/* The sample content handler */
static int helloworld_handler(request_rec *r)
{
if (strcmp(r->handler, "helloworld")) {
return DECLINED;
}
r->content_type = "text/html";
if (!r->header_only)
ap_rputs("The sample page from mod_helloworld.c\n", r);
return OK;
}
static void helloworld_register_hooks(apr_pool_t *p)
{
ap_hook_handler(helloworld_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA helloworld_module = {
STANDARD20_MODULE_STUFF,
NULL, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
NULL, /* create per-server config structures */
NULL, /* merge per-server config structures */
NULL, /* table of config file commands */
helloworld_register_hooks /* register hooks */
};
代碼注釋里有helloworld模塊實現(xiàn)的步驟,參考執(zhí)行:apxs -c -i mod_helloworld.c
蝇闭,這一步執(zhí)行的就是編譯了吠裆。如果apache不是按照默認目錄安裝匾鸥,可能需要修改Makefile文件里的路徑桅滋。
加載模塊岔乔,找到apache2.conf配置文件拇砰,在里面添加如下配置即可:
LoadModule helloworld_module modules/mod_helloworld
<Location /helloworld>
SetHandler helloworld
</Location>
我這個環(huán)境稍有不同脱篙,在瀏覽器登錄的歡迎界面就說到:
The configuration layout for an Apache2 web server installation on Ubuntu systems is as follows:
/etc/apache2/
|-- apache2.conf
| `-- ports.conf
|-- mods-enabled
| |-- *.load
| `-- *.conf
|-- conf-enabled
| `-- *.conf
|-- sites-enabled
| `-- *.conf
它把apache的配置文件拆成了小配置文件,在apache2.conf文件里include悦施,mods-enabled文件夾像是用來管理模塊的并扇,但是你會發(fā)現(xiàn)里面全是mods-available鏈接過來的文件,so仿照mods-available文件夾里面的文件格式抡诞,將helloworld模塊的配置文件分成兩部分:
helloworld.conf:
<Location /helloworld>
SetHandler helloworld
</Location>
helloworld.load:
LoadModule helloworld_module /usr/lib/apache2/modules/mod_helloworld.so
但是僅僅這樣還不行穷蛹,你還需要將模塊鏈接到mod_available文件夾下面,鏈接的方法也寫在apache服務(wù)器的歡迎頁面了:
They are activated by symlinking available configuration files from their respective *-available/ counterparts. These should be managed by using our helpers a2enmod, a2dismod,a2ensite, a2dissite,and a2enconf, a2disconf . See their respective man pages for detailed information.
使用sudo a2enmod helloworld
完成鏈接昼汗。
重啟apache服務(wù)器apachectl restart
肴熏,也可以按照提示使用service apache2 restart
,再然后就可以見證奇跡了顷窒,在主機瀏覽器里輸入http://192.168.232.129/helloworld蛙吏,出現(xiàn)The sample page from mod_helloworld.c
界面:
代碼里可見這個模塊只做了很少的事情,檢查r-handler是否是helloworld鞋吉,若不是出刷,返回DECLINED(代表處理器和請求不匹配,拒絕處理該請求)坯辩。
1.2 地獄版
獲取Apache最常用的三組信息:請求報頭馁龟、響應(yīng)抱頭和內(nèi)部環(huán)境變量。
修改mod_helloworld.c:
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
static int printitem(void *rec, const char *key, const char *value)
{
request_rec *r = rec;
ap_rprintf(r, "<tr><th scope=\"row\">%s</th><td>%s</td></tr>\n",
ap_escape_html(r->pool, key),
ap_escape_html(r->pool, value));
return 1;
}
static void printtable(request_rec *r, apr_table_t *t, const char *caption, const char *keyhead, const char *valhead)
{
ap_rprintf(r, "<table><caption>%s</caption><thead>"
"<tr><th scope=\"col\">%s</th><th scope=\"col\">%s"
"</th></tr></thead><tbody>", caption, keyhead, valhead);
apr_table_do(printitem, r, t, NULL);
ap_rputs("</tbody></table>\n", r);
}
/* The sample content handler */
static int helloworld_handler(request_rec *r)
{
if (!r->handler || strcmp(r->handler, "helloworld") != 0 ) {
return DECLINED;
}
if (r->method_number != M_GET) {
return HTTP_METHOD_NOT_ALLOWED;
}
ap_set_content_type(r, "text/html;charset=ascii");
ap_rputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n"
"<html><head><title>Apache Helloworld Module</title></head>"
"<body><h1>Hello World</h1>"
"<p>This is the Helloworld Module</p>", r);
/*打印表格*/
printtable(r, r->headers_in, "Request Headers", "Header", "Value");
printtable(r, r->headers_out, "Response Headers", "Header", "Value");
printtable(r, r->subprocess_env, "Environment", "Variable", "Value");
ap_rputs("</body></html>", r);
return OK;
}
static void helloworld_register_hooks(apr_pool_t *p)
{
ap_hook_handler(helloworld_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA helloworld_module = {
STANDARD20_MODULE_STUFF,
NULL, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
NULL, /* create per-server config structures */
NULL, /* merge per-server config structures */
NULL, /* table of config file commands */
helloworld_register_hooks /* register hooks */
};
重啟后如下圖:
1.3 其他
printitem回調(diào)函數(shù)
apr_table_do(func, rec, table, NULL) ;對表進行迭代
ap_escape_html
面向過濾器的I/O
三個步驟:
- 創(chuàng)建一個Bucket brigade
- 加載數(shù)據(jù)到Brigade
- 把Brigade傳遞到堆棧(r->output_filters)的第一個輸出過濾器中漆魔。
2 手動編輯
安裝apxs:
apt-get install apache2-dev
DECLINED:
#define DECLINED -1 /**< Module declines to handle */
request_rec:
/** A structure that represents the current request */
struct request_rec {
/** The handler string that we use to call a handler function */
const char *handler; /* What we *really* dispatch on */
/** Request method (eg. GET, HEAD, POST, etc.) */
const char *method;
/** M_GET, M_POST, etc. */
int method_number;
/** The filename on disk corresponding to this response */
char *filename;
}
ap_rputs:
/**
* Output a string for the current request
* @param str The string to output
* @param r The current request
* @return The number of bytes sent
* @deffunc int ap_rputs(const char *str, request_rec *r)
*/
AP_DECLARE(int) ap_rputs(const char *str, request_rec *r);
ap_set_content_length:
/**
* Set the content length for this request
* @param r The current request
* @param length The new content length
* @deffunc void ap_set_content_length(request_rec *r, apr_off_t length)
*/
AP_DECLARE(void) ap_set_content_length(request_rec *r, apr_off_t length);