前言
上一博
nginx指令开发时变量处理一
介绍了一种指令中出现变量的处理方法,今天再介绍一种方法。
步骤
假设命令如下:
my_test_var $arg_channel
意思是:通过url的请求参数中channel来确定做某件事。
模块名为:ngx_http_my_test_var_module
1. 配置结构体如下
typedef struct {
ngx_array_t *values;
ngx_array_t *lengths;
} ngx_http_test_var_conf_t;
2 ngx_command_t 定义
{ ngx_string("my_test_var"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_my_test_var_handler,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
3 ngx_http_my_test_var_handler函数实现如下
static char *
ngx_http_my_test_var_handler(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_test_var_conf_t *tvcf = conf;
ngx_str_t *value;
ngx_array_t *lengths, *values;
ngx_http_script_compile_t sc;
if (tvcf->lengths != NGX_CONF_UNSET_PTR) {
return "is duplicate";
}
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
lengths = NULL;
values = NULL;
value = cf->args->elts;
sc.cf = cf;
sc.source = &value[1];
sc.lengths = &lengths;
sc.values = &values;
sc.complete_lengths = 1;
sc.complete_values = 1;
if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_CONF_ERROR;
}
tvcf->lengths = lengths->elts;
tvcf->values = values->elts;
return NGX_CONF_OK;
}
4 需要说明一点:在init时,需要设置如下初值
tvcf->lengths = NGX_CONF_UNSET_PTR
tvcf->values = NGX_CONF_UNSET_PTR
5 在filter或者在需要用到变量的时候
ngx_http_test_var_conf_t *tvcf = ngx_http_get_module_loc_conf(r, ngx_http_my_test_var_module);
ngx_str_t val;
/*获取到的值已经存放在字符串val中*/
if (ngx_http_script_run(r, &val, tvcf->lengths, 0, tvcf->values) == NULL) {
return NGX_ERROR;
}
ngx_log_error(NGX_LOG_ERR, r->log, 0, "[test var value]%V", &val);
结束语
当然变量还有很多更高级的用法,比如条件表达式,但是有了以上两种方式处理变量,再加上对于指令中常量的处理,写一般的nginx module就容易了。更深入的用法后续再续