公式サイトより
IfIsEvilを訳してみた
http://wiki.nginx.org/IfIsEvil
Introduction
ifはlocationコンテキストで予期せぬ動作をすることがある、SIGSEGV(セグメンテーション違反)となることも
ただしifの中がreturn…とrewrite…lastのみ利用しているときは100%安全
またランダムで動作することはないため評価をしっかりしておけば利用しても問題は起こらない
また下の例のように、変数の評価(評価用のdirectiveが存在しない)をするときにifを利用を避けられない場合もある
if ($request_method = POST ) { return 405; } if ($args ~ post=140){ rewrite ^ http://example.com/ permanent; }
What to do instead
return…とrewrite…lastの利用を除き、try_filesを利用したほうがよい
また下の例のように、locationへの記載でなく、server contextへの記載に変更できる場合もある
それ以外にも他のモジュールを利用することで回避できることも
location / { error_page 418 = @other; recursive_error_pages on; if ($something) { return 418; } # some configuration ... } location @other { # some other configuration ... }
Examples
IfIsEvilの実例、この動作は仕様でありバグではない
only-one-if
location /only-one-if { set $true 1; if ($true) { add_header X-First 1; } if ($true) { add_header X-Second 2; } return 204; }
他のサーバからアクセスすると
### 2つめのヘッダしか付与されない ### root@akat:/home/shimizu# curl --dump-header - http://49.212.204.46/only-one-if HTTP/1.1 204 No Content Server: nginx/1.2.1 Date: Sun, 07 Sep 2014 10:42:03 GMT Connection: keep-alive X-Second: 2
proxy-pass-uri
location /proxy-pass-uri { proxy_pass http://www.google.co.jp/; set $true 1; if ($true) { # nothing } }
他のサーバからアクセスすると
### ifを通過後、proxy_passからredirectする ### root@akat:/home/shimizu# curl --dump-header - http://49.212.204.46/proxy-pass-uri HTTP/1.1 404 Not Found Server: nginx/1.2.1 Date: Sun, 07 Sep 2014 11:13:28 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 1439 Connection: keep-alive X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Alternate-Protocol: 80:quic <!DOCTYPE html> <html lang=en> <meta charset=utf-8> <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width"> <title>Error 404 (Not Found)!!1</title> <style> *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/errors/logo_sm_2.png) no-repeat}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/errors/logo_sm_2_hr.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/errors/logo_sm_2_hr.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/errors/logo_sm_2_hr.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:55px;width:150px} </style> <a href=//www.google.com/><span id=logo aria-label=Google></span></a> <p><b>404.</b> <ins>That’s an error.</ins> <p>The requested URL <code>/proxy-pass-uri</code> was not found on this server. <ins>That’s all we know.</ins>
if-try-files
location /if-try-files { try_files /file @fallback; set $true 1; if ($true) { # nothing } }
他のサーバからアクセスすると
### try_filesは動作しない ### root@akat:/home/shimizu# curl --dump-header - http://49.212.204.46/if-try-files HTTP/1.1 404 Not Found Server: nginx/1.2.1 Date: Sun, 07 Sep 2014 11:19:02 GMT Content-Type: text/html Content-Length: 168 Connection: keep-alive <html> <head><title>404 Not Found</title></head> <body bgcolor="white"> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.2.1</center> </body> </html>
crash
location /crash { set $true 1; if ($true) { # fastcgi_pass here fastcgi_pass 127.0.0.1:9000; } if ($true) { # no handler here } }
他のサーバからアクセスすると
### SIGSEGV(セグメンテーション違反) fastcgi_pass・proxy_passなどは利用しないほうがよい ### root@akat:/home/shimizu# curl --dump-header - http://49.212.204.46/crash curl: (52) Empty reply from server
Why this happens and still not fixed
通常のディレクティブは順番に処理されるが、ifディレクティブはrewrite moduleの一部であり、早い段階で評価される。
ifの中にnon-rewriteディレクティブがあると、上のような動作となる
ifの中のnon-rewriteディレクティブを無効にすることが、ただしいfixであるが、多くの設定に影響があるため対応できていない
If you still want to use if
それでもifを利用したい場合は、動作を理解し、ちゃんとテストして利用すること
参考URL
公式サイト-IfIsEvil-
http://wiki.nginx.org/IfIsEvil
nginxのifに要注意
http://www.techscore.com/blog/2012/10/31/nginx%E3%81%AEif%E3%81%AB%E8%A6%81%E6%B3%A8%E6%84%8F/
How nginx “location if” works
http://agentzh.blogspot.jp/2011/03/how-nginx-location-if-works.html