# HG changeset patch # User Vladimir Homutov # Date 1491577638 -10800 # Node ID d0aebb2337ec5ea1688ff0e4c49b81e754f398c2 # Parent 95a7e6eb5270b6109dd22b2782af359f6168c086 Added the "Variables" section to the development guide. diff -r 95a7e6eb5270 -r d0aebb2337ec xml/en/docs/dev/development_guide.xml --- a/xml/en/docs/dev/development_guide.xml Fri Apr 07 16:44:20 2017 +0300 +++ b/xml/en/docs/dev/development_guide.xml Fri Apr 07 18:07:18 2017 +0300 @@ -4246,6 +4246,394 @@ +
+ +
+ + +Variables may be referenced using index (this is the most common method) +or names (see below in the section about creating variables). +Index is created at configuration stage, when a variable is added +to configuration. +The variable index can be obtained using +ngx_http_get_variable_index(): + +ngx_str_t name; /* ngx_string("foo") */ +ngx_int_t index; + +index = ngx_http_get_variable_index(cf, &name); + +Here, the cf is a pointer to nginx configuration and the +name points to a string with the variable name. +The function returns NGX_ERROR on error or valid index +otherwise, which is typically stored somewhere in a module configuration for +future use. + + + +All HTTP variables are evaluated in the context of HTTP request and results +are specific to and cached in HTTP request. +All functions that evaluate variables return +ngx_http_variable_value_t type, representing +the variable value: + +typedef ngx_variable_value_t ngx_http_variable_value_t; + +typedef struct { + unsigned len:28; + + unsigned valid:1; + unsigned no_cacheable:1; + unsigned not_found:1; + unsigned escape:1; + + u_char *data; +} ngx_variable_value_t; + +where: + + + +len — length of a value + + + +data — value itself + + + +valid — value is valid + + + +not_found — variable was not found and thus +the data and len fields are irrelevant; +this may happen, for example, with such variables as $arg_foo +when a corresponding argument was not passed in a request + + + +no_cacheable — do not cache result + + + +escape — used internally by the logging module to mark +values that require escaping on output + + + + + + +The ngx_http_get_flushed_variable() +and ngx_http_get_indexed_variable() functions +are used to obtain the variable value. +They have the same interface - accepting a HTTP request r +as a context for evaluating the variable and an index, +identifying it. +Example of typical usage: + +ngx_http_variable_value_t *v; + +v = ngx_http_get_flushed_variable(r, index); + +if (v == NULL || v->not_found) { + /* we failed to get value or there is no such variable, handle it */ + return NGX_ERROR; +} + +/* some meaningful value is found */ + +The difference between functions is that the +ngx_http_get_indexed_variable() returns cached value +and ngx_http_get_flushed_variable() flushes cache for +non-cacheable variables. + + + +There are cases when it is required to deal with variables which names are +not known at configuration time and thus they cannot be accessed using indexes, +for example in modules like SSI or Perl. +The ngx_http_get_variable(r, name, key) function may be +used in such cases. +It searches for the variable with a given +name and its hash key. + + +
+ + +
+ + +To create a variable ngx_http_add_variable() function +is used. +It takes configuration (where variable is registered), variable name and +flags that control its behaviour: + + +NGX_HTTP_VAR_CHANGEABLE  — allows redefining +the variable; If another module will define a variable with such name, +no conflict will happen. +For example, this allows user to override variables using the + directive. + + +NGX_HTTP_VAR_NOCACHEABLE  — disables caching, +is useful for such variables as $time_local + + +NGX_HTTP_VAR_NOHASH  — indicates that +this variable is only accessible by index, not by name. +This is a small optimization which may be used when it is known that the +variable is not needed in modules like SSI or Perl. + + +NGX_HTTP_VAR_PREFIX  — the name of this +variable is a prefix. +A handler must implement additional logic to obtain value of specific +variable. +For example, all “arg_” variables are processed by the +same handler which performs lookup in request arguments and returns value +of specific argument. + + + + +The function returns NULL in case of error or a pointer to +ngx_http_variable_t: + +struct ngx_http_variable_s { + ngx_str_t name; + ngx_http_set_variable_pt set_handler; + ngx_http_get_variable_pt get_handler; + uintptr_t data; + ngx_uint_t flags; + ngx_uint_t index; +}; + + +The get and set handlers +are called to obtain or set the variable value, +data will be passed to variable handlers, +index will hold assigned variable index, used to reference +the variable. + + + +Usually, a null-terminated static array of such structures is created +by a module and processed at the preconfiguration stage to add variables +into configuration: + +static ngx_http_variable_t ngx_http_foo_vars[] = { + + { ngx_string("foo_v1"), NULL, ngx_http_foo_v1_variable, NULL, 0, 0 }, + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + +static ngx_int_t +ngx_http_foo_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var, *v; + + for (v = ngx_http_foo_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; + } + + return NGX_OK; +} + +This function is used to initialize the preconfiguration +field of the HTTP module context and is called before parsing HTTP configuration, +so it could refer to these variables. + + + +The get handler is responsible for evaluating the variable +in a context of specific request, for example: + +static ngx_int_t +ngx_http_variable_connection(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%uA", r->connection->number) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + +It returns NGX_ERROR in case of internal error +(for example, failed memory allocation) or NGX_OK otherwise. +The status of variable evaluation may be understood by inspecting flags +of the ngx_http_variable_value_t (see description above). + + + +The set handler allows setting the property +referred by the variable. +For example, the $limit_rate variable set handler +modifies the request's limit_rate field: + +... +{ ngx_string("limit_rate"), ngx_http_variable_request_set_size, + ngx_http_variable_request_get_size, + offsetof(ngx_http_request_t, limit_rate), + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, +... + +static void +ngx_http_variable_request_set_size(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ssize_t s, *sp; + ngx_str_t val; + + val.len = v->len; + val.data = v->data; + + s = ngx_parse_size(&val); + + if (s == NGX_ERROR) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "invalid size \"%V\"", &val); + return; + } + + sp = (ssize_t *) ((char *) r + data); + + *sp = s; + + return; +} + + + + +
+ +
+ + +
+ + +A complex value, despite its name, provides an easy way to evaluate +expressions that may contain text, variables, and their combination. + + + +The complex value description in +ngx_http_compile_complex_value is compiled at the +configuration stage into ngx_http_complex_value_t +which is used at runtime to obtain evaluated expression results. + + +ngx_str_t *value; +ngx_http_complex_value_t cv; +ngx_http_compile_complex_value_t ccv; + +value = cf->args->elts; /* directive arguments */ + +ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + +ccv.cf = cf; +ccv.value = &value[1]; +ccv.complex_value = &cv; +ccv.zero = 1; +ccv.conf_prefix = 1; + +if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; +} + + +Here, ccv holds all parameters that are required to +initialize the complex value cv: + + + + +cf — configuration pointer + + + +value — string for parsing (input) + + + +complex_value — compiled value (output) + + + +zero — flag that enables zero-terminating value + + + +conf_prefix — prefixes result with configuration prefix +(the directory where nginx is currently looking for configuration) + + + +root_prefix — prefixes result with root prefix +(this is the normal nginx installation prefix) + + + +The zero flag is usable when results are to be passed to +libraries that require zero-terminated strings, and prefixes are handy when +dealing with filenames. + + + +Upon successful compilation, cv.lengths may +be inspected to get information about the presence of variables +in the expression. +The NULL value means that the expression contained static text only, +and there is no need in storing it as a complex value, +so a simple string can be used. + + + +The ngx_http_set_complex_value_slot() is a convenient +function used to initialize complex value completely right in the directive +declaration. + + + +At runtime, a complex value may be calculated using the +ngx_http_complex_value() function: + +ngx_str_t res; + +if (ngx_http_complex_value(r, &cv, &res) != NGX_OK) { + return NGX_ERROR; +} + +Given the request r and previously compiled +value cv the function will evaluate +expression and put result into res. + + +
+ +