Nginx将第三方模块编译到nginx中的方法:将源代码文件和config放在一个目录中,然后执行configure --add-module=PATH (以上文件的地址) ,就可以在执行正常编译安装流程时完成nginx编译工作;
通过编写配置mytest模块,可以在http{},server{},location{}块中声明配置mytest,如
location /mytest/ {
mytest;
}
那么当用户请求的URI中匹配到/mytest/ ,就会调用我们自定义的ngx_mytest_handle方法来处理这个用户请求;
1、编写config文件
ngx_addon_name=ngx_http_mytest_module
HTTP_MODULES="$HTTP_MODULES ngx_http_mytest_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest_module.c"
- ngx_addon_name:仅在configure执行时使用,一般设置为模块
- HTTP_MODULES:保存所有的HTTP模块名称,每个HTTP模块间由空格符相连。在重新设置HTTP_MODULES变量时,不要直接覆盖它,因为configure调用到自定义的config脚本前,已经将各个HTTP模块设置到HTTP_MODULES变量中了,因此,要像如下这样设
"$HTTP_MODULES ngx_http_mytest_module"
- NGX_ADDON_SRCS:用于指定新增模块的源代码,多个待编译的源代码间以空格符相连。注意,在设置NGX_ADDON_SRCS时可以使用$ngx_addon_dir变量,它等价于configure执行时--add-module=PATH的PATH参数。
2、编写ngx_http_mytest_module.c
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
//mytest配置项处理
static ngx_int_t ngx_http_mytest_handle(ngx_http_request_t *r){
//必须是GET或者HEAD方法,否则返回405 Not Allowed
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;
}
//设置返回的Content-Type
ngx_str_t type = ngx_string("text/html;application/json;charset=utf-8");
//返回的包体的内容
ngx_str_t response = ngx_string("Hello World!");
//设置返回的状态码
r->headers_out.status = NGX_HTTP_OK;
//响应包体是有包体内容的,需要设置Contetn-Length长度
r->headers_out.content_length_n = response.len;
//设置contetn-type
r->headers_out.content_type = type;
//发送自定义头部
ngx_table_elt_t* h = ngx_list_push(&r->headers_out.headers);
if(h == NULL){
return NGX_ERROR;
}
h->hash = 1;
h->key.len = sizeof("TestHead")-1;
h->key.data = (u_char *) "TestHead";
h->value.len = sizeof("TestValue") - 1;
h->value.data = (u_char *) "TestValue";
//发送HTTP头部
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only){
return rc;
}
//构建ngx_buf_t结构体准备发送包体
ngx_buf_t *b;
b = ngx_create_temp_buf(r->pool,response.len);
if (b == NULL){
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
//将responser复制到ngx_buf_t指向的内存中
ngx_memcpy(b->pos,response.data,response.len);
//注意,一定要设置好last指针
b->last = b->pos + response.len;
//声明这是最后一块缓存区
b->last_buf = 1;
//构造发送时的ngx_chain_t结构体
ngx_chain_t out;
//赋值ngx_buf_t
out.buf = b;
//设置next为null
out.next = NULL;
//最后一步为发送包体,发送结束后http框架会调用ngx_http_finalize_request方法结束请求
return ngx_http_output_filter(r,&out);
}
static char *
ngx_http_mytest(ngx_conf_t *cf,ngx_command_t *cmd,void *conf){
//首先找到mytest配置项所属的配置块;
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf,ngx_http_core_module);
//如果请求的主机域名、URI、与mytest配置项所在的配置块相匹配,会调用我们实现的ngx_http_mytest_handle
clcf->handler = ngx_http_mytest_handle;
return NGX_CONF_OK;
}
static ngx_command_t ngx_http_mytest_commands[] = {
{
ngx_string("mytest"), //配置项名称
//配置项类型,指定配置项可以出现的位置
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS,
//处理配置项的参数,当配置块中出现mytest配置项时,Nginx会调用ngx_http_mytest方法
ngx_http_mytest,
//在配置文件中的偏移量
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL
},
ngx_null_command
};
//第三方模块可以介入HTTP框架7个阶段处理请求,如果有什么需要在http框架初始化完成的,就可以在这里设置
static ngx_http_module_t ngx_http_mytest_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL, /* merge location configuration */
};
//定义mytest模块
ngx_module_t ngx_http_mytest_module = {
NGX_MODULE_V1,
&ngx_http_mytest_module_ctx, /* module context */
ngx_http_mytest_commands, /* modele directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
3、编译该模块
#运行configure文件,使用--add-module=PATH(config和ngx_module_http_mytest_module所在的问文件夹)
./configure --add-module=/usr/local/nginx-1.14.2/nginx-module/mytest-module
make
nginx -s stop
cp objs/nginx ../../nginx/sbin
#启动nginx
nginx