`

apache 模块编写

阅读更多
http://blog.csdn.net/hqin6/archive/2011/01/27/6166750.aspx
路径为:/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即可!
上面讲了整个apache模块的搭建工作,以及编译和链接的命令和步骤,下面讲讲关于apache模块的开发:
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
下面是我写的一个函数,用来得到参数的,仅供参考!
view plaincopy to clipboardprint?

   1. char* get_args_param(request_rec* r, const char* name) 
   2. {/*{{{*/ 
   3.     const char* args = r->args; 
   4.     const char* start_args; 
   5.     if (NULL != args) 
   6.     { 
   7.         for (start_args = ap_strstr_c(args, name); start_args; 
   8.                 start_args = ap_strstr_c(start_args + 1, name)) 
   9.         { 
  10.             if (start_args == args || start_args[-1] == '&' || isspace(start_args[-1])) 
  11.             { 
  12.                 start_args += strlen(name); 
  13.                 while (*start_args && isspace(*start_args)) 
  14.                     ++start_args; 
  15.                 if (*start_args == '=' && start_args[1]) 
  16.                 { 
  17.                     char* end_args; 
  18.                     char* arg; 
  19.                     ++start_args; 
  20.                     arg = apr_pstrdup(r->pool, start_args); 
  21.                     if ((end_args = strchr(arg, '&')) != NULL) 
  22.                         *end_args = '\0'; 
  23.                     return arg; 
  24.                 } 
  25.             } 
  26.         } 
  27.     } 
  28.     return NULL; 
  29. }/*}}}*/ 

char* get_args_param(request_rec* r, const char* name) {/*{{{*/ const char* args = r->args; const char* 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; }/*}}}*/
这里借鉴了源码中的get_cookie_param的编写!下面会提到!
这里需要注意,对于apr_pstrdup函数的调用,需要包含头文件:#include "apr_strings.h",否则会有警告,并且在运行的时候会core掉!
这里的apr_pstrdup所分配的内存,不需要显式free,它是基于apr_pool_t,当request end后,一次性释放!
第二个问题:如何得到特定的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吧!
view plaincopy to clipboardprint?

   1. char *get_cookie_param(request_rec *r, const char *name) 
   2. {/*{{{*/ 
   3.     const char *cookies; 
   4.     const char *start_cookie; 
   5.     if ((cookies = apr_table_get(r->headers_in, "Cookie"))) { 
   6.         for (start_cookie = ap_strstr_c(cookies, name); start_cookie; 
   7.                 start_cookie = ap_strstr_c(start_cookie + 1, name)) { 
   8.             if (start_cookie == cookies || 
   9.                     start_cookie[-1] == ';' || 
  10.                     start_cookie[-1] == ',' || 
  11.                     isspace(start_cookie[-1])) { 
  12.                 start_cookie += strlen(name); 
  13.                 while(*start_cookie && isspace(*start_cookie)) 
  14.                     ++start_cookie; 
  15.                 if (*start_cookie == '=' && start_cookie[1]) { 
  16.                     char *end_cookie, *cookie; 
  17.                     ++start_cookie; 
  18.                     cookie = apr_pstrdup(r->pool, start_cookie); 
  19.                     if ((end_cookie = strchr(cookie, ';')) != NULL) 
  20.                         *end_cookie = '\0';  
  21.                     if((end_cookie = strchr(cookie, ',')) != NULL) 
  22.                         *end_cookie = '\0';  
  23.                     return cookie;  
  24.                 } 
  25.             } 
  26.         } 
  27.     } 
  28.     return NULL; 
  29. }/*}}}*/ 

char *get_cookie_param(request_rec *r, const char *name) {/*{{{*/ const char *cookies; const char *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; }/*}}}*/
还有很多其他参数,比如User-Agent,Referer,Accept-Charset,Keep-Alive等很多头信息都在这个headers_in里,下面的这个网址可以找到你想要的:
http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
比如,取到User-Agent:apr_table_get(r->headers_in, "User-Agent");
第三个问题:如何取得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.iteye.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
分享到:
评论

相关推荐

    apache 模块开发的例子

    2. 编程语言:Apache模块可以用C或C++编写,因为Apache本身是用C编写的,这能确保最佳性能和直接访问底层API。 3. API接口:Apache提供了一套丰富的API,如`ap_create_request()`用于创建请求对象,`ap_add_output_...

    window环境下apache模块开发工具apxs及安装使用详细说明

    1. **Apache模块API**:熟悉Apache的API,如`APR(Apache Portable Runtime)`,`Apache2xx`函数等,是编写模块的基础。 2. **编译环境**:设置好C/C++编译环境,例如Visual Studio或MinGW。 3. **Apache运行时库**...

    apache模块开发入门

    ### Apache模块开发基础知识点 #### 一、Apache简介与特性 Apache是一款开源的Web服务器软件,以其稳定性、安全性以及灵活性而著称。它通过插件(模块)的形式提供了丰富的功能扩展,如`mod_proxy`用于代理服务,`...

    apache模块开发入门级资料

    Apache模块开发是构建高效Web服务器的关键技术之一,它允许开发者根据特定需求定制和扩展Apache的功能。这份入门级资料集合提供了丰富的资源,涵盖了从基础到进阶的多个方面,旨在帮助初学者快速掌握Apache模块开发...

    Apache模块开发指南

    《Apache模块开发指南》是一本专注于...通过阅读《Apache模块开发指南》这本书,你可以获得以上所有知识的详细解释和实例,从而能够熟练地开发和维护自己的Apache模块,为构建高效、定制化的Web服务环境打下坚实基础。

    Web服务器软件Apache模块初步研究总结.doc

    Apache模块是Apache web服务器的核心组成部分,允许开发者通过编写C语言的插件来扩展服务器功能。Apache模块API提供了丰富的功能,让开发人员能够实现特定的Web服务需求,如配置处理、内容生成、URL重写和日志记录等...

    apache 相关工具模块

    标签“源码”和“工具”暗示了这个压缩包可能包含了Apache模块的源代码以及与之相关的开发或调试工具。源码意味着我们可以深入理解模块的工作原理,并对其进行修改和定制,以满足特定的Web服务需求。而“工具”可能...

    Writing Apache Modules with Perl and C

    还是apache模块编写 不过有些历史了 希望有用 只象征性收一分

    cpp-modwsgi是一个Apache模块实现了PythonWSGI接口服务

    这个模块,通常称为`mod_wsgi`,使得开发者可以使用Python语言来编写Web应用,并在Apache环境下运行。在本文中,我们将深入探讨`mod_wsgi`的工作原理、其重要性以及如何使用它。 首先,让我们理解WSGI。Web服务器...

    swift-用Swift编写ApacheModules

    通过编写Apache模块,开发者可以根据需求定制服务器的行为。 在Swift中编写Apache模块,我们需要依赖Apache的模块开发接口(API)以及Apache的模块开发工具。Apache提供了一套名为`mod_swift`的模块,它使得在Swift...

    C语言-apache mod(模块开发)-采用VS2017开发范例

    Apache模块是Apache HTTP服务器的核心功能扩展,通过编写C语言代码并编译成动态链接库(.so或.dll),我们可以实现自定义的Web服务功能。在本范例中,我们将使用Visual Studio 2017(VS2017)作为开发环境来创建一个...

    C语言-apache mod(模块开发)-采用centos7.2 apxs的开发范例

    Apache模块是Apache HTTP服务器功能的扩展,通过C语言编写,可以增强服务器的性能或提供新的服务。本教程将深入探讨如何在CentOS 7.2环境下使用apxs工具来开发Apache模块。 首先,Apache mod(模块)是Apache服务器...

    安装apache mysql php 手册&&开发apache,php扩展模块方法

    3. 配置PHP,同时指定Apache模块(确保Apache已安装且在路径中):`./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql=/usr/local/mysql --with-config-file-path=/etc/php.ini` 4. 编译和安装:`...

    支持apache2.2.x版本的iasp模块源文件

    这个模块允许在 Apache 上运行基于微软技术的 ASP 应用程序,从而打破了原本只能在 Microsoft IIS 上运行 ASP 的局限。源文件的标题表明这适用于 Apache 2.2.x 版本,这是一个稳定且广泛使用的 Apache 版本。 **ASP...

    apache(httpd)源码

    1. **Apache源码**:Apache的源码由C语言编写,包含了服务器的核心功能和模块,如HTTP协议处理、多线程模型、模块化设计等。通过阅读和理解源码,开发者可以定制服务器的行为,添加新功能,或优化性能。`apache-...

    Nginx服务器中的模块编写及相关内核源码初探

    模块编写过程可以分为以下步骤: 1. 创建模块文件夹 2. 创建模块配置文件 3. 创建模块主文件 在创建模块的过程中,开发者需要包含必要的Nginx核心库文件,如ngx_config.h、ngx_core.h、ngx_http.h等,并实现与HTTP...

    关于Delphi7的IntraWeb编译的Apache(DSO)模块

    ### 关于Delphi7的IntraWeb编译的Apache(DSO)模块 #### Delphi7与IntraWeb Delphi7是一款由Borland公司开发的集成开发环境(Integrated Development Environment,IDE),主要针对Windows平台进行应用程序开发。它...

Global site tag (gtag.js) - Google Analytics