I have read https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/
I want to check if my rails application has already added a header (Access-Control-Allow-Origin
) and if it hasn't then add the header.
The examples here have tried to explain the behaviour of if
condition in nginx.conf http://agentzh.blogspot.in/2011/03/how-nginx-location-if-works.html
But I have not understood it. One of the question I have is what is meant when they say a directive or phase directive?
I have tried some things myself. Like:
location / {
add_header My-outer-header '*';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
if($sent_http_access_control_allow_origin != /*){
add_header My-inner-header '**';
}
}
Here when the if condition is met, only My-inner-header
is set and not the My-outer-header
.
But when I do:
location / {
add_header My-outer-header '*';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
set $a 1;
if($a == 1){
add_header My-inner-header '**';
}
}
Here $a variable is set to 1 but only the My-inner-header
is set again and not the My-outer-header
.
I want to check and ensure if the instructions like proxy_set_header
are getting executed or not.
I haven't tested your code. I only speak from experience!!!
To begin with, allow me to specify that Nginx configuration is NOT at all similar to any OOP behaviour (Object Oriented Programming). It is in a single word unpredictably "Declarative".
Meaning... If you have 2 IF statements in the same block that both meet the criteria, ONLY the second will prevail and be executed.
The same happens with 1 if and all it's previous declarations in the same block. Some variables (Not all) will not be executed due to the presence of IF, and nginx expects them to be re-declared within. This happens in your example. Let's take the second one for clarity. Inside your location block, you declare several header values. BUT, when the IF statement is met, they are NOT executed (IF is evil in nginx indeed). In order to have a full execution you need to re-declare most of your header variables inside and anything else outside the if, again inside the if statement, so they will be executed in case the if statement is met. NOTE, there is no map that lists all the variable affected by IF in nginx and you should test our conf for any errors. Some variables will NOT need to be re-declared and in this case nginx will report an error on restart. Only way to figure out which, is go for all and rule out the reported erroneous ones.
Suggestions
a) Avoid IF in nginx if possible. Use location blocks instead. e.g. If you simply want to add a header variable like Access-Control-Allow-Origin for certain files, do NOT use if, but instead a second location block (See below)
location / {
// some code here
}
location ~* \.(eot|ttf|woff|woff2)$ {
add_header Access-Control-Allow-Origin *;
}
b) In cases where IF is mandatory, use with caution and test test test. As above, re-declaring everything in the if statement is a good practice (As above suggested, test and rule out whichever re-declaration breaks configuration).
Good luck.