In (a) we mentioned that the value of the Nginx variable has only one type, that is, the string, but the variable may not have a meaningful value at all. A variable that has no value also has two special values: one is "illegal" (invalid) and the other is "not found" (not found).
For example, when the Nginx user variable is $foo
created and not assigned, $foo
the value is "illegal" and if the parameter is not mentioned in the URL parameter string of the current request XXX
, then the value of the _xxx built-in variable is "not found".
Whether it's "illegal" or "not found", these two Nginx variables have special values, and the empty string ("") the value is completely different, such as the JavaScript language also has special undefined
and null
these two special values, and Lua language also has a special c5/> values: They are neither equivalent to an empty string, nor to a number, nor to a 0
Boolean value false
. In fact, the SQL language NULL
is a similar thing.
Although we see earlier in (a) that the variable created by the set directive is used in "variable interpolation", the effect is equivalent to an empty string, but that is because the set directive automatically registers a "fetch handler" for the variable it creates and converts the "illegal" variable value to an empty string. To verify this, let's look again at the example discussed in (a):
Location/foo {
echo "foo = [$foo]";
}
Location/bar {
Set $foo 32;
echo "foo = [$foo]";
}
For the sake of simplicity, it omits the previously written perimeter server
configuration block. In this example, we /bar
implicitly create the name of the variable in the interface with the set directive $foo
, and then we /foo
$foo
use the echo command output directly in the interface without initializing it. /foo
The result of our test interface was
$ Curl ' Http://localhost:8080/foo '
foo = []
From the output, the uninitialized $foo
variable does exactly the same as an empty string. But the attentive reader should have noticed at the time that, for the above request, the Nginx error log file (the general filename is called) has one error.log
more line in it similar to the following warning:
[Warn] 5765#0: * * using uninitialized "foo" variable, ...
Who is the one who output this line of warning? The answer is that the SET command is the $foo
"fetch handler" for the registration. When the /foo
echo instruction in the interface is actually executed, it "foo = [$foo]"
calculates the "variable interpolation" of its parameters. Then, the variable in the argument string is $foo
read, and Nginx first checks its value in the container, and as a result it sees the "illegal" value, so it decides to continue calling the $foo
"fetch handler" of the variable. The $foo
"fetch handler" of the variable starts running, it prints out the warning message to the Nginx error log, and then returns an empty string as $foo
the value and is cached in $foo
the value container.
Careful readers will notice that the process just described is actually the work of the built-in variables that support the value cache, except that the set directive borrows this mechanism to handle Nginx variables that are not properly initialized. It is worth mentioning that only the "illegal" this special value will trigger the NGINX call variable "fetch handler", and the special value "not found" but not.
The above warning usually indicates that there is a typo in the variable name in our Nginx configuration, or that a variable that has not been initialized has been used in the wrong situation. Because of the presence of a value cache, this warning is not printed more than once during the lifetime of a request. Of course, the Ngx_rewrite module specifically provides a Uninitialized_variable_warn configuration directive that can be used to suppress this warning log.
As mentioned earlier, the built-in variable $arg _xxx XXX
returns a special value "not found" when the request URL parameter does not exist, but unfortunately it is not easy to distinguish it from an empty string in the Nginx native configuration language (which we estimate and call it), such as:
location/test {
echo "Name: [$arg _name]";
}
Here we output $arg_name
the value of the variable and intentionally does not provide the URL parameter in the request name
:
$ Curl ' http://localhost:8080/test '
Name: []
As we can see, the output special value "not found" effect and the empty string is the same. Because this time is Nginx's "variable interpolation" engine automatically "can't find" to ignore.
So how do we capture the "can't find" trace of this particular value? In other words, how should we differentiate it from the empty string? Obviously, in the following request, the URL parameter name
is a value, and its value should be an empty string:
$ Curl ' http://localhost:8080/test?name= '
Name: []
But we are unable to distinguish it from name
the situation where the parameters are not provided at all.
Fortunately, with third-party module Ngx_lua, we can easily do this in LUA code. Take a look at the following example:
location /test {
content_by_lua '
if Ngx.var.arg_name == nil then
ngx.say ("name: missing")
else
ngx.say ("name: [", ngx.var.arg_name, "]")
end
' ;
}
This example is very close to the previous example, except that we /test
use the Content_by_lua configuration directive of the Ngx_lua module in the interface, embedding a small section of our own LUA code to $arg_name
judge the special values of Nginx variables. In this example, when $arg_name
the value is "not found" (or "illegal"), the /foo
interface outputs name: missing
this line of results:
Curl ' http://localhost:8080/test '
Name:missing
Because this is the first time we have access to the Ngx_lua module, we need a brief introduction first. The Ngx_lua module embeds the LUA language interpreter (or the Luajit instant compiler) into the Nginx core, allowing the user to run a program written in the Lua language directly in the Nginx core. We can choose to insert our Lua code in the different request processing stages of Nginx. These Lua codes can be either directly inline in an Nginx configuration file or placed separately in an external .lua
file, and then refer to .lua
the path of the file in the Nginx configuration file.
Back to the example above, we quoted the Nginx variable in the LUA code through ngx.var
the LUA interface provided by the Ngx_lua module. For example, when you reference Nginx variables $VARIABLE
, you can write Ngx.var.VARIABLE in Lua code. When the Nginx variable $arg_name
is a special value "not Found" (or "illegal"), the ngx.var.arg_name
value in the LUA world is the nil
"null" in the LUA language (unlike the LUA empty string). When we output the response body content in Lua, we use the Ngx.say Lua function, which is also provided by the Ngx_lua module, which is functionally equivalent to the echo configuration instruction of the Ngx_echo module.
Now, if we provide an argument for an empty string value name
, the output is not the same as it was just now:
$ Curl ' http://localhost:8080/test?name= '
Name: []
In this case, the $arg_name
value of the Nginx variable is an empty string, which is neither "not found" nor "illegal", so in Lua, the Lua ngx.var.arg_name
empty string ("") is returned, and the LUA value just now is nil
completely distinguishable.
This distinction is very important in some scenarios, such as the existence of a Web service interface that name
determines whether a collection of data is name
filtered by attributes, rather than providing an empty string as the value of the parameter, and name
also causing the value in the data set to be empty string To filter the records.
However, there are some limitations to the standard $arg _xxx variables, such as we use this request to test the /test
interface just now:
$ Curl ' http://localhost:8080/test?name '
Name:missing
At this point, the $arg_name
variable still reads "Can't find" this special value, which is obviously a violation of common sense. In addition, $arg the _XXX variable has multiple parameters with the same name in the request URL XXX
, it only returns the value of the first XXX
parameter, silently ignoring the other instance:
$ Curl ' Http://localhost:8080/test?name=Tom&name=Jim&name=Bob '
Name: [Tom]
To address these limitations, you can use the Ngx.req.get_uri_args function provided by the Ngx_lua module directly in Lua code.
(not to be continued)
Discussion on Nginx variable (vii)