ngx.var.arg_xxngx.req.get_uri_args["xx"] 两者都是为了获取请求 uri 中的参数,例如对于 url:

http://pureage.info?strider=1  

为了获取输入参数 strider,以下两种方法都可以:

local strider = ngx.var.arg_strider
local strider = ngx.req.get_uri_args["strider"]

差别在于,当请求 uri 中有多个同名参数时,ngx.var.arg_xx 的做法是取第一个出现的值,ngx.req_get_uri_args["xx"] 的做法是返回一个 table,该 table 里存放了该参数的所有值,例如,当请求 uri 为:

http://pureage.info?strider=1&strider=2&strider=3&strider=4  

此时,ngx.var.arg_strider 的值为“1”,而 ngx.req.get_uri_args["strider"] 的值为 table ["1", "2", "3", "4"]。因此,ngx.req.get_uri_args 属于ngx.var.arg_ 的增强。

ngx.var.arg_ 的实现是直接使用 Nginx 原生的变量支持,Nginx 相关代码为:

ngx_http_variable_value_t *  
ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)  
{  
....(略)....  
if (ngx_strncmp(name->data, "arg_", 4) == 0) {  
  
        if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) {  
            return vv;  
        }  
  
        return NULL;  
    }  
  
    vv->not_found = 1;  
  
    return vv;  
}  
  
static ngx_int_t  
ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,  
    uintptr_t data)  
{  
    ngx_str_t *name = (ngx_str_t *) data;  
  
    u_char *arg;  
    size_t len;  
    ngx_str_t value;  
  
    len = name->len - (sizeof("arg_") - 1);  
    arg = name->data + sizeof("arg_") - 1;  
  
    if (ngx_http_arg(r, arg, len, &value) != NGX_OK) {  
        v->not_found = 1;  
        return NGX_OK;  
    }  
  
    v->data = value.data;  
    v->len = value.len;  
    v->valid = 1;  
    v->no_cacheable = 0;  
    v->not_found = 0;  
  
    return NGX_OK;  
}  
  
ngx_int_t  
ngx_http_arg(ngx_http_request_t *r, u_char *name, size_t len, ngx_str_t *value)  
{  
    u_char *p, *last;  
  
    if (r->args.len == 0) {  
        return NGX_DECLINED;  
    }  
  
    p = r->args.data;  
    last = p + r->args.len;  
  
    for ( /* void */ ; p < last; p++) {  
  
        /* we need '=' after name, so drop one char from last */  
  
        p = ngx_strlcasestrn(p, last - 1, name, len - 1);  
  
        if (p == NULL) {  
            return NGX_DECLINED;  
        }  
  
        if ((p == r->args.data || *(p - 1) == '&') && *(p + len) == '=') {  
  
            value->data = p + len + 1;  
  
            p = ngx_strlchr(p, last, '&');  
  
            if (p == NULL) {  
                p = r->args.data + r->args.len;  
            }  
  
            value->len = p - value->data;  
  
            return NGX_OK;  
        }  
    }  
  
    return NGX_DECLINED;  
}