Web Notes
2016.08.20
Using Liquid in Jekyll - Live with Demos
Liquid is a simple template language that Jekyll uses to process pages for your site. With Liquid you can output complex contents without additional plugins.
Note took from:
Nginx’s configuration files use a micro programming language, variables are thus a natural part of it. Variables are just containers holding various values in imperative languages like Perl, C/C++, and Bash. However, for the Nginx configuration language, variables can hold only one type of values, that is, strings (exception, the 3rd-party module ngx_array_var extends Nginx variables to hold arrays, implemented by encoding a C pointer as a binary string value behind the scene).
For example, in nginx.conf
we set:
set $a "hello world";
Which assigns a value (string value of hello world
) to the variable $a
via the set
configuration directive (coming from ngx_rewrite module). This syntax is required by Nginx: whenever we want to reference an Nginx variable, we must add a $
prefix. And variables in Nginx can be embedded directly into a string literal:
set $a "hello";
set $b "$a, $a";
So after above two directives complete execution, the value of $a
is hello
, and $b
is hello, hello
. This technique is called variable interpolation in the Perl world, which makes ad-hoc string concatenation operators no longer necessary.
Let’s see another complete example:
server {
listen 8080;
location /text {
set $foo "hello";
echo "foo: $foo";
}
}
To request this /test
interface via curl
, we get:
$ curl 'http://localhost:8080/test'
foo: hello
Here in this example, echo
directive of 3rd-party module nginx_echo
was used, which support variable interpolation. But we cannot take it for granted for other directives, always loop up the documentation to be sure.
To output a literal $
character via echo
directive, the following naive example does NOT work at all:
location /t {
echo "$";
}
We will get the following error message while loading this configuration:
[emerg] invalid variable name in ...
Luckily, workarounds do exist:
geo $dollar {
default "$";
}
...
location /t {
echo "This is a dollar sign: $dollar";
}
Here we make use of the geo
directive of the standard module nginx_geo
to initialise the $dollar
variable with the string $
, thereafter variable $dollar
can be used in places that require a dollar sign. This works because the geo
directive does not support variable interpolation at all.
There is a special case for variable interpolation, that is, when the variable name is followed directly by characters allowed in variable name (like letters, digits, and underscores). In such cases, we can use a special notation to disambiguate the variable name from the subsequent literal characters, for instance:
location /test {
set $first "hello ";
echo "${first}world";
}
If it was written directly as $firstworld
, Nginx variable interpolation engine (also known as the script engine) will try to access the variable $firstworld
instead of $first
. To address the ambiguity here, curly braces must be used.
Just like variables in C/C++, which must be declared before they can be used so that the compiler can allocate storage and perform type checking at compile time. Nginx creates all the variables while loading the configuration file, that is, variable creation only occurs when Nginx loads its configuration.
Once an Nginx variable is created, it is visible to the entire configuration, even across different virtual server configuration blocks.
Here is an example:
location /foo {
echo "foo = [$foo]";
}
location /bar {
set $foo 32;
echo "foo = [$foo]";
}
Here, the variable $foo
is created by the set
directive inside location /bar
, and this variable is visible to the entire Nginx configuration. It should be noted that when requesting the /foo
interface, we always get an empty value for the $foo
variable because that is what we get when accessing an uninitialised variable.
Another important characteristic that we can observe from this example is that even though the scope of Nginx variable is the entire configuration, each request does have its own version of all those variables’ containers. Requests do not interfere with each other even if they are referencing a variable with the same name.
There is another common misunderstanding: assume that the lifetime of Nginx variables are bound to the location
configuration block. Let’s consider the following example:
location /foo {
set $a "hello";
echo_exec /bar;
}
location /bar {
echo "a = [$a]";
}
The internal redirection is an operation that makes Nginx jump from one location to another while processing a request. this jumping happens completely within the server itself. This is different from those external redirections based on HTTP 301
and 302
responses because the latter is collaborated externally by the HTTP clients. Also, in case of external redirections, the end user could usually observe the change of the URL in the web browser’s address bar while this is not the case for internal ones. Internal redirections are very similar to the exec
command in Bash; it is a one way trip and never returns.
Back to the example, the whole process looks like this: Nginx first assigns to the $a
variable in location /foo
, and then it issues and internal redirection via echo_exec
, thus leaving location /foo
and entering location /bar
, and finally it outputs the value of $a
.
$ curl "http://localhost:8080/foo"
a = [hello]
To conclude, the lifetime of Nginx variable containers is indeed bound to the request being processed, and is irrelevant to
location
.
Variables without any meaningful values still take a special value though in Nginx. There are two possible special values: invalid and not found.
For example, when a user variable $foo
is created but not assigned yet, $foo
takes the special value of “invalid”. And when the current URL query string does not have the xxx
argument at all, the built-in variable $arg_xxx
takes the special value of “not found”.
Both invalid and not found are special values, completely different from an empty string value (“”).
It is also worth noting that only the invalid special value will trigger the “get handler” invocation in the Nginx core while not found will not.
Frank Lin
Web Notes
2016.08.20
Liquid is a simple template language that Jekyll uses to process pages for your site. With Liquid you can output complex contents without additional plugins.
JavaScript Notes
2018.12.17
JavaScript is a very function-oriented language. As we know, functions are first class objects and can be easily assigned to variables, passed as arguments, returned from another function invocation, or stored into data structures. A function can access variable outside of it. But what happens when an outer variable changes? Does a function get the most recent value or the one that existed when the function was created? Also, what happens when a function invoked in another place - does it get access to the outer variables of the new place?
Tools
2020.09.12
Location directives are essential when working with Nginx. They can be located within server blocks or other location blocks. Understanding how location directives are used to process the URI of client request can help make the request handling less unpredictable.