Mercurial > hg > nginx-site
changeset 1959:d0aebb2337ec
Added the "Variables" section to the development guide.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Fri, 07 Apr 2017 18:07:18 +0300 |
parents | 95a7e6eb5270 |
children | 9550ea66abdd |
files | xml/en/docs/dev/development_guide.xml |
diffstat | 1 files changed, 388 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- 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 @@ </section> +<section name="Variables" id="http_variables"> + +<section name="Accessing existing variables" id="http_existing_variables"> + +<para> +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 +<literal>ngx_http_get_variable_index()</literal>: +<programlisting> +ngx_str_t name; /* ngx_string("foo") */ +ngx_int_t index; + +index = ngx_http_get_variable_index(cf, &name); +</programlisting> +Here, the <literal>cf</literal> is a pointer to nginx configuration and the +<literal>name</literal> points to a string with the variable name. +The function returns <literal>NGX_ERROR</literal> on error or valid index +otherwise, which is typically stored somewhere in a module configuration for +future use. +</para> + +<para> +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 +<literal>ngx_http_variable_value_t</literal> type, representing +the variable value: +<programlisting> +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; +</programlisting> +where: +<list type="bullet"> + +<listitem> +<literal>len</literal> — length of a value +</listitem> + +<listitem> +<literal>data</literal> — value itself +</listitem> + +<listitem> +<literal>valid</literal> — value is valid +</listitem> + +<listitem> +<literal>not_found</literal> — variable was not found and thus +the <literal>data</literal> and <literal>len</literal> fields are irrelevant; +this may happen, for example, with such variables as <var>$arg_foo</var> +when a corresponding argument was not passed in a request +</listitem> + +<listitem> +<literal>no_cacheable</literal> — do not cache result +</listitem> + +<listitem> +<literal>escape</literal> — used internally by the logging module to mark +values that require escaping on output +</listitem> + +</list> +</para> + +<para> +The <literal>ngx_http_get_flushed_variable()</literal> +and <literal>ngx_http_get_indexed_variable()</literal> functions +are used to obtain the variable value. +They have the same interface - accepting a HTTP request <literal>r</literal> +as a context for evaluating the variable and an <literal>index</literal>, +identifying it. +Example of typical usage: +<programlisting> +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 */ +</programlisting> +The difference between functions is that the +<literal>ngx_http_get_indexed_variable()</literal> returns cached value +and <literal>ngx_http_get_flushed_variable()</literal> flushes cache for +non-cacheable variables. +</para> + +<para> +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 <literal>ngx_http_get_variable(r, name, key)</literal> function may be +used in such cases. +It searches for the <literal>variable</literal> with a given +<literal>name</literal> and its hash <literal>key</literal>. +</para> + +</section> + + +<section name="Creating variables" id="http_creating_variables"> + +<para> +To create a variable <literal>ngx_http_add_variable()</literal> function +is used. +It takes configuration (where variable is registered), variable name and +flags that control its behaviour: + +<list type="bullet"> +<listitem><literal>NGX_HTTP_VAR_CHANGEABLE</literal> — 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 +<link doc="../http/ngx_http_rewrite_module.xml" id="set"/> directive. +</listitem> + +<listitem><literal>NGX_HTTP_VAR_NOCACHEABLE</literal> — disables caching, +is useful for such variables as <literal>$time_local</literal> +</listitem> + +<listitem><literal>NGX_HTTP_VAR_NOHASH</literal> — 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. +</listitem> + +<listitem><literal>NGX_HTTP_VAR_PREFIX</literal> — the name of this +variable is a prefix. +A handler must implement additional logic to obtain value of specific +variable. +For example, all “<literal>arg_</literal>” variables are processed by the +same handler which performs lookup in request arguments and returns value +of specific argument. +</listitem> + +</list> + +The function returns NULL in case of error or a pointer to +<literal>ngx_http_variable_t</literal>: +<programlisting> +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; +}; +</programlisting> + +The <literal>get</literal> and <literal>set</literal> handlers +are called to obtain or set the variable value, +<literal>data</literal> will be passed to variable handlers, +<literal>index</literal> will hold assigned variable index, used to reference +the variable. +</para> + +<para> +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: +<programlisting> +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; +} +</programlisting> +This function is used to initialize the <literal>preconfiguration</literal> +field of the HTTP module context and is called before parsing HTTP configuration, +so it could refer to these variables. +</para> + +<para> +The <literal>get</literal> handler is responsible for evaluating the variable +in a context of specific request, for example: +<programlisting> +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; +} +</programlisting> +It returns <literal>NGX_ERROR</literal> in case of internal error +(for example, failed memory allocation) or <literal>NGX_OK</literal> otherwise. +The status of variable evaluation may be understood by inspecting flags +of the <literal>ngx_http_variable_value_t</literal> (see description above). +</para> + +<para> +The <literal>set</literal> handler allows setting the property +referred by the variable. +For example, the <literal>$limit_rate</literal> variable set handler +modifies the request's <literal>limit_rate</literal> field: +<programlisting> +... +{ 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; +} +</programlisting> + +</para> + +</section> + +</section> + + +<section name="Complex values" id="http_complex_values"> + +<para> +A complex value, despite its name, provides an easy way to evaluate +expressions that may contain text, variables, and their combination. +</para> + +<para> +The complex value description in +<literal>ngx_http_compile_complex_value</literal> is compiled at the +configuration stage into <literal>ngx_http_complex_value_t</literal> +which is used at runtime to obtain evaluated expression results. + +<programlisting> +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; +} +</programlisting> + +Here, <literal>ccv</literal> holds all parameters that are required to +initialize the complex value <literal>cv</literal>: + +<list type="bullet"> + +<listitem> +<literal>cf</literal> — configuration pointer +</listitem> + +<listitem> +<literal>value</literal> — string for parsing (input) +</listitem> + +<listitem> +<literal>complex_value</literal> — compiled value (output) +</listitem> + +<listitem> +<literal>zero</literal> — flag that enables zero-terminating value +</listitem> + +<listitem> +<literal>conf_prefix</literal> — prefixes result with configuration prefix +(the directory where nginx is currently looking for configuration) +</listitem> + +<listitem> +<literal>root_prefix</literal> — prefixes result with root prefix +(this is the normal nginx installation prefix) +</listitem> + +</list> +The <literal>zero</literal> flag is usable when results are to be passed to +libraries that require zero-terminated strings, and prefixes are handy when +dealing with filenames. +</para> + +<para> +Upon successful compilation, <literal>cv.lengths</literal> 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. +</para> + +<para> +The <literal>ngx_http_set_complex_value_slot()</literal> is a convenient +function used to initialize complex value completely right in the directive +declaration. +</para> + +<para> +At runtime, a complex value may be calculated using the +<literal>ngx_http_complex_value()</literal> function: +<programlisting> +ngx_str_t res; + +if (ngx_http_complex_value(r, &cv, &res) != NGX_OK) { + return NGX_ERROR; +} +</programlisting> +Given the request <literal>r</literal> and previously compiled +value <literal>cv</literal> the function will evaluate +expression and put result into <literal>res</literal>. +</para> + +</section> + + <section name="Load balancing" id="http_load_balancing"> <para>