编写nginx自定义c模块需理解其静态编译机制、模块生命周期及http处理流程;必须集成源码并重新编译,核心包含配置结构体、上下文结构体和模块定义结构体三部分,典型示例通过ngx_http_hello_module实现location级响应。

编写 Nginx 自定义 C 模块需要理解其模块生命周期、配置解析机制和 HTTP 处理流程。Nginx 的模块体系是静态编译型的,不支持运行时动态加载(除非使用 ngx_http_lua_module 或第三方 patch),因此必须将 C 模块源码集成进 Nginx 源码树并重新编译整个 Nginx。
模块结构与核心文件组成
一个基础的 HTTP 模块通常包含以下三个关键部分:
-
模块配置结构体:定义模块的配置项(如指令、上下文、默认值),对应
ngx_command_t数组 -
模块上下文结构体:声明模块的生命周期回调函数(
create_conf、merge_conf、postconfiguration等) -
模块定义结构体:全局唯一的
ngx_http_module_t实例,注册模块名、上下文、指令表和版本信息
模块源文件一般命名为 ngx_http_hello_module.c,放在 src/http/modules/ 下(或自定义目录,需在 configure 中指定)。
编写一个最简 HTTP 模块示例
以下是一个返回固定字符串的最小可运行模块(ngx_http_hello_module.c):
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h><p>static char <em>ngx_http_hello_world(ngx_conf_t </em>cf, ngx_command_t <em>cmd, void </em>conf);
static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r);</p>
<p>static ngx_command_t ngx_http_hello_commands[] = {
{ ngx_string("hello_world"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_http_hello_world,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
ngx_null_command
};</p>
<p>static ngx_http_module_t ngx_http_hello_module_ctx = {
NULL, /<em> preconfiguration </em>/
NULL, /<em> postconfiguration </em>/
NULL, /<em> create main configuration </em>/
NULL, /<em> init main configuration </em>/
NULL, /<em> create server configuration </em>/
NULL, /<em> merge server configuration </em>/
NULL, /<em> create location configuration </em>/
NULL /<em> merge location configuration </em>/
};</p>
<p>ngx_module_t ngx_http_hello_module = {
NGX_MODULE_V1,
&ngx_http_hello_module_ctx, /<em> module context </em>/
ngx_http_hello_commands, /<em> module directives </em>/
NGX_HTTP_MODULE, /<em> module type </em>/
NULL, /<em> init master </em>/
NULL, /<em> init module </em>/
NULL, /<em> init process </em>/
NULL, /<em> init thread </em>/
NULL, /<em> exit thread </em>/
NULL, /<em> exit process </em>/
NULL, /<em> exit master </em>/
NGX_MODULE_V1_PADDING
};</p>
<p>static char <em>
ngx_http_hello_world(ngx_conf_t </em>cf, ngx_command_t <em>cmd, void </em>conf) {
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_hello_handler;
return NGX_CONF_OK;
}</p>
<p>static ngx_int_t
ngx_http_hello_handler(ngx_http_request_t *r) {
if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
return NGX_HTTP_NOT_ALLOWED;
}</p>
<pre class="brush:php;toolbar:false;">ngx_int_t rc = ngx_http_discard_request_body(r);
if (rc != NGX_OK) {
return rc;
}
ngx_str_t type = ngx_string("text/plain");
ngx_str_t resp = ngx_string("Hello from custom Nginx module!\n");
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = resp.len;
r->headers_out.content_type = type;
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
return rc;
}
return ngx_http_output_filter(r, &r->out);
}
编译集成进 Nginx 源码
不能单独 gcc -shared 编译成 so 文件后加载 —— Nginx 官方不支持标准 dlopen 方式加载 HTTP 模块。
- 把模块源文件(如
ngx_http_hello_module.c)放入 Nginx 源码目录,例如src/http/modules/ - 修改
src/http/modules/ngx_http_modules.c,在模块数组末尾添加你的模块引用:&ngx_http_hello_module, - 进入 Nginx 源码根目录,执行 configure 并启用该模块:
./configure --add-module=./path/to/your/module(推荐方式,无需改源码) - 运行
make && sudo make install
使用 --add-module 是最安全、最常用的方式,它会自动将模块加入构建系统,无需手动修改 ngx_http_modules.c。
在 nginx.conf 中启用模块
编译安装后,在配置中使用你定义的指令即可:
location /hello {
hello_world;
}
重启 Nginx 后访问 http://localhost/hello 即可看到响应。
注意:模块指令作用域需匹配(如上面用的是 NGX_HTTP_LOC_CONF,就必须放在 location 块中);若想支持 server 级别,需调整指令标志并实现对应的 handler 绑定逻辑。











