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/
posted @ 2021-10-17 11:27  onefiter  阅读(298)  评论(0)    收藏  举报