Nginx的mirror模块详解

1.相关指令

1
2
3
4
5
6
7
8
9
10
Syntax:	mirror uri | off;
Default:
mirror off;
Context: http, server, location

Syntax: mirror_request_body on | off;
Default:
mirror_request_body on;
Context: http, server, location

2.配置解析函数

首先看下指令mirror的配置解析函数ngx_http_mirror的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
static char *
ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_mirror_loc_conf_t *mlcf = conf;

ngx_str_t *value, *s;

value = cf->args->elts;
//判断参数是否为off
if (ngx_strcmp(value[1].data, "off") == 0) {
if (mlcf->mirror != NGX_CONF_UNSET_PTR) {
return "is duplicate";
}

mlcf->mirror = NULL;
return NGX_CONF_OK;
}

if (mlcf->mirror == NULL) {
return "is duplicate";
}
// 构造数组mlcf->mirror
if (mlcf->mirror == NGX_CONF_UNSET_PTR) {
mlcf->mirror = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
if (mlcf->mirror == NULL) {
return NGX_CONF_ERROR;
}
}
// push一个数组元素,用于保存mirror配置
s = ngx_array_push(mlcf->mirror);
if (s == NULL) {
return NGX_CONF_ERROR;
}
// 保存参数,也就是url
*s = value[1];

return NGX_CONF_OK;
}

接下来看看handler函数ngx_http_mirror_handler的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
static ngx_int_t
ngx_http_mirror_handler(ngx_http_request_t *r)
{
ngx_int_t rc;
ngx_http_mirror_ctx_t *ctx;
ngx_http_mirror_loc_conf_t *mlcf;
// 子请求,直接返回
if (r != r->main) {
return NGX_DECLINED;
}
// 获取location级别的配置
mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module);
// 没有配置mirror,直接返回
if (mlcf->mirror == NULL) {
return NGX_DECLINED;
}

ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mirror handler");
// 处理请求body
if (mlcf->request_body) {
ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module);

if (ctx) {
return ctx->status;
}
// 申请ctx内存
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_mirror_ctx_t));
if (ctx == NULL) {
return NGX_ERROR;
}

ctx->status = NGX_DONE;
// 设置ctx
ngx_http_set_ctx(r, ctx, ngx_http_mirror_module);
// 读request_body
rc = ngx_http_read_client_request_body(r, ngx_http_mirror_body_handler);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
// 结束请求
ngx_http_finalize_request(r, NGX_DONE);
return NGX_DONE;
}
// 调用handler
return ngx_http_mirror_handler_internal(r);
}

接下来看看ngx_http_mirror_body_handler处理逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
static void
ngx_http_mirror_body_handler(ngx_http_request_t *r)
{
ngx_http_mirror_ctx_t *ctx;
// get ctx
ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module);
//调用internal
ctx->status = ngx_http_mirror_handler_internal(r);

r->preserve_body = 1;
// 重新执行各个阶段
r->write_event_handler = ngx_http_core_run_phases;
ngx_http_core_run_phases(r);
}

接下来看下ngx_http_mirror_init的处理逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static ngx_int_t
ngx_http_mirror_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;

cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
// precontent阶段,push出一个元素,用于保存handler
h = ngx_array_push(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
// handler赋值
*h = ngx_http_mirror_handler;

return NGX_OK;
}

接下来看看ngx_http_mirror_handler_internal实现,主要是遍历所有mirror指令,创建子请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
static ngx_int_t
ngx_http_mirror_handler_internal(ngx_http_request_t *r)
{
ngx_str_t *name;
ngx_uint_t i;
ngx_http_request_t *sr;
ngx_http_mirror_loc_conf_t *mlcf;

mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module);

name = mlcf->mirror->elts;
// 遍历location下的mirror指令
for (i = 0; i < mlcf->mirror->nelts; i++) {
//创建子请求
if (ngx_http_subrequest(r, &name[i], &r->args, &sr, NULL,
NGX_HTTP_SUBREQUEST_BACKGROUND)
!= NGX_OK)
{
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}

sr->header_only = 1;
sr->method = r->method;
sr->method_name = r->method_name;
}

return NGX_DECLINED;
}

以上就是mirror模块主要功能