美文网首页
helloworld_mod模块

helloworld_mod模块

作者: 御浅永夜 | 来源:发表于2017-11-12 23:17 被阅读0次

    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);
    

    相关文章

      网友评论

          本文标题:helloworld_mod模块

          本文链接:https://www.haomeiwen.com/subject/nxwomxtx.html