Not sure what you mean by safe, but let me tell about a case I ran into recently. I needed to deny access to a site unless a certain parameter is passed. Let's say the config looked like this:
server {
server_name localhost;
root /usr/share/nginx/html;
try_files $uri /index.html;
}
I added an if
:
...
if ($arg_secret-key != 123456) {
return 404;
}
But nginx
would give me 404 even if I provided the secret:
$ curl -sS localhost/?secret-key=123456
It turned out that try_files
made an internal redirect to /index.html
(not passing the parameter), which resulted in 404. So to make it work it needed to be this way:
try_files $uri /index.html$is_args$args;
But actually I had to deny access to the main page only:
...
location = / {
if ($arg_secret-key != 123456) {
return 404;
}
}
And this way it worked w/o changing try_files
. That's because there's also the index
module. And try_files
doesn't get inherited by the location
block. As such, the index
module makes the right redirect to /index.html?secret-key=123456
, and for the new request there's nothing left to do for try_files
.
If you're not sure what's happening, you might want to run nginx
built with --with-debug
and configure the error log with the debug
level, e.g.:
nginx.conf
:
error_log /var/log/nginx/error.log debug;
server {
server_name localhost;
root /usr/share/nginx/html;
...
}
$ docker run --rm --name nginx -p 1111:80 -dv $PWD/nginx.conf:/etc/nginx/conf.d/default.conf nginx:alpine nginx-debug -g 'daemon off;'
// launch `docker logs -f nginx` in a separate console, use Enter to separate requests
// processing starts with "generic phase: 0"
$ curl -sS localhost:1111/?secret-key=123456
// change nginx.conf
$ docker exec nginx nginx -s reload
$ curl -sS localhost:1111/?secret-key=123456
...
$ docker stop nginx
More on it here.
About your second question, I think that in your case having 2 server
's is preferable. Because that's suggested by developers, and if you choose the if
version, one day you might run into some issue after changing the config. Or you might realize that in some cases it doesn't work the way you expected it to (in more complex cases). One might say, if
introduces complexity into the config you might not know about. As such I'd use if
if I had a good understanding of how it all works, or had no other option. And the if
version looks like it might be worse performance-wise. Although that's just a speculation, and I can't provide any numbers. In my case I don't see any workaround, as such that's what I'm going to use for now.