Nginx的return模块

1 相关配置

return模块配置指令如下:

1
return value;

详细用法参考nginx官方文档

2 源码解析

2.1 首先看看指令解析函数,这个函数的主要功能就是把return指令后面的文本以nginx变量的形式保存,绑定此阶段的处理函数。

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
static char *
ngx_stream_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_stream_return_srv_conf_t *rscf = conf;

ngx_str_t *value;
ngx_stream_core_srv_conf_t *cscf;
ngx_stream_compile_complex_value_t ccv;

if (rscf->text.value.data) {
return "is duplicate";
}

value = cf->args->elts;

ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));

ccv.cf = cf;
ccv.value = &value[1];
ccv.complex_value = &rscf->text;

if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
return NGX_CONF_ERROR;
}

cscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_core_module);

cscf->handler = ngx_stream_return_handler;

return NGX_CONF_OK;
}

2.2 在上一步设置好处理函数后,nginx运行到此阶段就会调用ngx_stream_return_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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

static void
ngx_stream_return_handler(ngx_stream_session_t *s)
{
ngx_str_t text;
ngx_buf_t *b;
ngx_connection_t *c;
ngx_stream_return_ctx_t *ctx;
ngx_stream_return_srv_conf_t *rscf;

c = s->connection;

c->log->action = "returning text";

rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_return_module);

// 获取变量值
if (ngx_stream_complex_value(s, &rscf->text, &text) != NGX_OK) {
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
}

ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
"stream return text: \"%V\"", &text);

if (text.len == 0) {
ngx_stream_finalize_session(s, NGX_STREAM_OK);
return;
}

// 分配上下文内存
ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_return_ctx_t));
if (ctx == NULL) {
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
}

// 设置模块上下文
ngx_stream_set_ctx(s, ctx, ngx_stream_return_module);

b = ngx_calloc_buf(c->pool);
if (b == NULL) {
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
}

b->memory = 1;
b->pos = text.data;
b->last = text.data + text.len;
b->last_buf = 1;

ctx->out = ngx_alloc_chain_link(c->pool);
if (ctx->out == NULL) {
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
}

// 挂载输出buf
ctx->out->buf = b;
ctx->out->next = NULL;

// 设置写回调函数
c->write->handler = ngx_stream_return_write_handler;

// 调用写回调函数
ngx_stream_return_write_handler(c->write);
}

ngx_stream_return_handler函数首先解析出return指令后面的字符串值,然后为当前模块的ngx_stream_return_ctx_t申请内存,主要用来挂载发送数据的chain,再为发送数据的chain以及buf申请内存,设置写事件的handler,最后发送响应到客户端。

3 总结

return模块属于stream模块,在stream模块中处于第4阶段,所以需要绑定handler函数,将return指令后的变量或者纯文本响应给客户端。