In some situations, if not most, you should avoid using if
blocks. There are two main issues occurring, regardless of the Nginx build you are using.
There are some cases where if
is used inappropriately, in a way that risks saturating your storage device with useless checks:
location / { # Redirect to index.php if the requested file is not found if (!-e $request_filename) { rewrite ^ index.php last; } }
With such a configuration, every single request received by Nginx will trigger a complete verification of the directory tree for the requested filename, thus requiring multiple storage disk access system calls. If you test /usr/local/nginx/html/hello.html
, Nginx will check /
, /usr
, /usr/local
, /usr/local/nginx
, and so on. In any case, you should avoid resorting to such a statement. For example, by filtering the file type beforehand (for instance, by making such a check, only if the requested file matches specific extensions):
location / { # Filter file extension first if ($request_filename !~ "\.(gif|jpg|jpeg|png)" { break; } if (!-f $request_filename) { rewrite ^ index.php last; } }
The if
block should ideally be employed for simple situations, as its behavior might be surprising in some cases. Apart from the fact that if
statements cannot be nested, the following situations may present issues:
# Two consecutive statements with the same condition: location / { if ($uri = "/test.html") { add_header X-Test-1 1; expires 7; } if ($uri = "/test.html") { add_header X-Test-1 1; } }
In this case, the first if
block is ignored and only the second one is processed. However, if you insert a Rewrite module directive in the first block, such as rewrite
, break
, or return
, the block will be processed and the second one will be ignored.
There are many other cases where the use of if
causes problems:
Having
try_files
andif
statements in the same location block is not recommended as thetry_files
directive will, in most cases, be ignored.Some directives are theoretically allowed within the
if
block but can create serious issues, for instance,proxy_pass
andfastcgi_pass
. You should keep those withinlocation
blocks.You should avoid using
if
blocks within alocation
block that captures regular expression patterns from its modifier.
The origin of these problems comes from the fact that while the Nginx configuration is established in a declarative language, directives from the Rewrite module such as if
, rewrite
, return
, or break
make it look like actual scripting. In general, you should try to avoid using directives from other modules within if
blocks as much as possible.