Nginx之自定义模块
Nginx之自定义模块
Nginx提供了一种简单的方式第三方的模块编译到Nginx中。首先将源代码文件全部放到的一个目录下,同时在该目录下编写一个文件通知Nginx如何编译本模块,这个文件必须是config。然后,只要在configure脚本执行时加入参数--add-module=PATH(源码路径),就可以在执行正常编译安装流程时完成Nginx编译工作。有时,以上这种方式无法满足需求时,在执行完configure脚本后Nginx会生成ogjs/Makefile和objs/nginx_modules.c文件,我们可以修改这些文件,虽然比较复杂。
1 | config文件的写法
- nginx_addon_name
- HTTP_MODULES
- NGX_ADDON_SRCS:用于指定新增的源代码,多个待编译的源代码间已空格符相连。
ngx_addon_name=ngx_http_onefiter_module
HTTP_MODULES="$HTTP_MODULES ngx_http_onefiter_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_onefiter_module.c"
2 | 利用configure脚本将定制的模块加入到Nginx中
struct ngx_module_s {
ngx_uint_t ctx_index;
ngx_uint_t index;
char *name;
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t version;
const char *signature;
void *ctx;
ngx_command_t *commands;
ngx_uint_t type;
ngx_int_t (*init_master)(ngx_log_t *log);
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);
void (*exit_master)(ngx_cycle_t *cycle);
uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};
3 | 编写ngx_http_onefiter_module
/*
* @Author: onefiter
* @Date: 2021-10-17 10:23:41
* @LastEditTime: 2021-10-17 10:42:53
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \nginx-1.16.1\onefitermodule\ngx_http_onefiter_module.c
*/
#include <ngx_config.h> //the packages of nginx
#include <ngx_core.h>
#include <ngx_http.h>
static void *ngx_http_onefiter_create_loc_conf(ngx_conf_t *cf);
static char * ngx_http_onefiter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_onefiter_handler(ngx_http_request_t *r);
typedef struct {
ngx_str_t secret;
} ngx_http_onefiter_conf_t;
static ngx_command_t ngx_http_onefiter_commands[] = {
{
ngx_string("onefiter"),
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
ngx_http_onefiter,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL,
},
ngx_null_command
};
static ngx_http_module_t ngx_http_onefiter_module_ctx = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
ngx_http_onefiter_create_loc_conf,
NULL
};
ngx_module_t ngx_http_onefiter_module = {
NGX_MODULE_V1,
&ngx_http_onefiter_module_ctx,
ngx_http_onefiter_commands,
NGX_HTTP_MODULE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NGX_MODULE_V1_PADDING
};
static void *ngx_http_onefiter_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_onefiter_conf_t * mycf;
mycf = ngx_palloc(cf->pool, sizeof(ngx_http_onefiter_conf_t));
if (mycf == NULL) {
return NGX_CONF_ERROR;
}
mycf->secret.len = 0;
mycf->secret.data = NULL;
return mycf;
}
static char * ngx_http_onefiter(ngx_conf_t *cf, ngx_command_t *cmd, void *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_onefiter_handler;
ngx_conf_set_str_slot(cf, cmd, conf);
return NGX_CONF_OK;
}
static ngx_int_t ngx_http_onefiter_handler(ngx_http_request_t *r)
{
if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) {
return NGX_HTTP_NOT_ALLOWED;
}
ngx_int_t rc = ngx_http_discard_request_body(r);
if (rc != NGX_OK) {
return rc;
}
ngx_http_onefiter_conf_t *mycf;
mycf = ngx_http_get_module_loc_conf(r, ngx_http_onefiter_module);
ngx_int_t isAuth = 0;
ngx_str_t format = ngx_string("secret=%V");
ngx_str_t match;
match.len = format.len - 2 + mycf->secret.len;
match.data = ngx_palloc(r->pool, match.len);
ngx_snprintf(match.data, match.len, "secret=%V", &mycf->secret);
ngx_uint_t i = 0;
if (r->args.len >= match.len) {
for (; i <= r->args.len - match.len; i++) {
if (0 == ngx_strncasecmp(r->args.data + i, match.data, match.len)) {
if (i < r->args.len - match.len && *(r->args.data + i + match.len) != '&') {
continue;
}
if (i != 0 && *(r->args.data + i - 1) != '&') {
continue;
}
isAuth = 1;
break;
}
}
}
ngx_str_t response;
if (isAuth == 1) {
ngx_str_set(&response, "secret right");
} else {
ngx_str_set(&response, "secret wrong");
}
ngx_str_t type = ngx_string("text/plain");
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = response.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;
}
ngx_buf_t *b;
b = ngx_create_temp_buf(r->pool, response.len);
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ngx_memcpy(b->pos, response.data, response.len);
b->last = b->pos + response.len;
b->last_buf = 1;
ngx_chain_t out;
out.buf = b;
out.next = NULL;
return ngx_http_output_filter(r, &out);
}
4 | 执行编译命令
./configure --prefix=/application/nginx-1.16/ --add-module=/home/codes/onefitermodule/ngx_http_onefiter_module
make
cp -i objs/nginx /application/nginx-1.16.0/sbin/
珍惜时间,不断实践!

浙公网安备 33010602011771号