Resources: https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/ Introduction Problem to If in Nginx is (Evil). The only 100% safe things which may be done inside if in a location context are: ```nginx return ...; rewrite ... last; ``` What to do instead Use try_files if it suits your needs. Use the “return ...” or “rewrite ... last” in other cases. In some cases, it’s also possible to move ifs to server level (where it’s safe as only other rewrite module directives are allowed within it). E.g. the following may be used to safely change location which will be used to process request: ```nginx if ($request_method = POST ) { return 405; } if ($args ~ post=140){ rewrite ^ http://example.com/ permanent; } ``` Examples Here are some examples which explain why if is evil. Don’t try this at home. You were warned. # Here is collection of unexpectedly buggy configurations to show that # if inside location is evil. # only second header will be present in response # not really bug, just how it works ```nginx location /only-one-if { set $true 1; if ($true) { add_header X-First 1; } if ($true) { add_header X-Second 2; } return 204; } ``` # request will be sent to backend without uri changed # to '/' due to if ```nginx location /proxy-pass-uri { proxy_pass http://127.0.0.1:8080/; set $true 1; if ($true) { # nothing } } ``` # try_files wont work due to if ```nginx location /if-try-files { try_files /file @fallback; set $true 1; if ($true) { # nothing } } ``` # nginx will SIGSEGV ```nginx location /crash { set $true 1; if ($true) { # fastcgi_pass here fastcgi_pass 127.0.0.1:9000; } if ($true) { # no handler here } } ``` # alias with captures isn't correcly inherited into implicit nested # location created by if ```nginx location ~* ^/if-and-alias/(?.*) { alias /tmp/$file; set $true 1; if ($true) { # nothing } } ```