Variables that are used by modules and are set inside ‘if’ blocks in the
nginx.conf file are not being set correctly. My nginx version (-V
output) is:
nginx version: nginx/0.7.64
built by gcc 4.3.3 (Ubuntu 4.3.3-5ubuntu4)
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_ssl_module
–add-module=…/nginx_http_push_module-0.69
–add-module=…/agentzh-echo-nginx-module-b8a0849
I’m setting $push_channel_id for the nginx_http_push_module using the
following if statement.
location ^~ /fjsub/ {
push_subscriber long-poll;
if ($arg_id) {
set $push_channel_id $arg_id;
}
}
The variable is set fine outside an ‘if’ statement but when the if
evaluates to true, the variable is not set.
I have duplicated this behaviour with the echo module as follows:
This will print “No”:
location ^~ /echo/ {
set $myText “No”;
if ($remote_addr ~* ‘000’){
set $myText “Yes”;
}
echo $myText;
}
But when I replace ‘000’ with ‘64’ which matches my IP address, nginx
returns a 404 because the value of $myText is empty which means the echo
command didn’t have any effect.
I have duplicated this behavior with only the echo module compiled in
and ssl and push removed.
I’ve already filed this as a bug on GIT for the NHPM (push) module but I
suspect this may be an nginx bug since it is broken across modules.
This bug also exists on the latest development build:
nginx version: nginx/0.8.28
built by gcc 4.3.3 (Ubuntu 4.3.3-5ubuntu4)
configure arguments: --prefix=/usr/local/nginx
–add-module=…/agentzh-echo-nginx-module-b8a0849
What is surprising/confusing is that I’m setting variables inside
conditional statements that are used by proxy_pass and that works fine.
So does the upstream module (proxy_pass module) handle it’s variables
differently to the echo and push modules?
What is surprising/confusing is that I’m setting variables inside
conditional statements that are used by proxy_pass and that works fine.
So does the upstream module (proxy_pass module) handle it’s variables
differently to the echo and push modules?
The “if” block is ugly hack inside nginx. This is the cause.
I run this in production with over 30,000 concurrent connections on the
nginx front end. nginx.conf laughs at apache2.conf and hits on it’s
girlfriend.
The variable is set fine outside an ‘if’ statement but when the if evaluates
to true, the variable is not set.
Behind the scene, the if directive’s “block” is implemented as a
dynamic location (of type LIF, not LOC). It’s very different from the
if statements’ blocks one usually finds in an everyday programming
language
I have duplicated this behaviour with the echo module as follows:
This will print “No”:
location ^~ /echo/ {
set $myText “No”;
if ($remote_addr ~* ‘000’){
set $myText “Yes”;
}
echo $myText;
}
Tests have shown that if the “if” condition succeeds here, nginx will
return a 404 error page because of the lack of content handler in that
anonymous location corresponding to the “if” block
I’ve just released “echo” module v0.22 to allow you to use “echo”
directly in “if” blocks and the following should work as expected:
location ^~ /if {
set $res miss;
if ($arg_val ~* '^a') {
set $res hit;
echo $res;
}
echo $res;
}
GET /if?val=abc yields the “hit” output while GET /if?val=bcd yields
“miss”
It seems that the standard proxy_pass directive also works in if blocks
(yay!):
location ^~ /if {
set $res miss;
if ($arg_val ~* '^a') {
set $res hit;
proxy_pass $scheme://127.0.0.1:$server_port/foo?res=$res;
}
proxy_pass $scheme://127.0.0.1:$server_port/foo?res=$res;
}
location /foo {
echo "res = $arg_res";
}
You will get the expected behavior
Feel free to take a look at more related (passing) test cases that
I’ve included in the “echo” module’s test suite: