helloworld_mod模块

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模块实现的步骤,参考执行:apxs -c -i mod_helloworld.c,这一步执行的就是编译了。如果apache不是按照默认目录安装,可能需要修改Makefile文件里的路径。
加载模块,找到apache2.conf配置文件,在里面添加如下配置即可:

LoadModule helloworld_module modules/mod_helloworld
<Location /helloworld>
SetHandler helloworld
</Location>

我这个环境稍有不同,在浏览器登录的欢迎界面就说到:

 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文件夹像是用来管理模块的,但是你会发现里面全是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服务器的欢迎页面了:

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服务器apachectl restart,也可以按照提示使用service apache2 restart,再然后就可以见证奇迹了,在主机浏览器里输入http://192.168.232.129/helloworld,出现The sample page from mod_helloworld.c界面:

apache-hellowrold2.png

代码里可见这个模块只做了很少的事情,检查r-handler是否是helloworld,若不是,返回DECLINED(代表处理器和请求不匹配,拒绝处理该请求)。

1.2 地狱版

获取Apache最常用的三组信息:请求报头、响应抱头和内部环境变量。
修改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                      */
};

重启后如下图:


apache-helloworld3.png

1.3 其他

printitem回调函数

apr_table_do(func, rec, table, NULL) ;对表进行迭代
ap_escape_html

面向过滤器的I/O

三个步骤:

  • 创建一个Bucket brigade
  • 加载数据到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);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容