NGINX の if は本当に “evil” なのか?

NGINX の if は本当に “evil” なのか?

IfIsEvil ドキュメントを読み解き、運用で失敗しないためのチェックリスト

1. はじめに

NGINX の設定サンプルを調べると、「if は evil だから使うな」という警告をよく目にします。実際に公式 Wiki の IfIsEvil ページでも強い表現が使われていますが、それは location コンテキスト内の if に限った話です。

2. IfIsEvil とは?

「ディレクティブ if には location コンテキストで問題がある」

“100% 安全” とされているのは returnrewrite ... last のみです。

3. なぜ location 内の if が危険なのか

3-1. 暗黙の “nested location” が発生する

rewrite モジュールと宣言型の設定のギャップにより、NGINX は内部で一時的な location を生成・破棄します。これにより副作用が起きる可能性があります。

3-2. 具体的な事故例

# add_header が片方しか付かない
location /only-one-if {
    set $true 1;
    if ($true) { add_header X-First 1; }
    if ($true) { add_header X-Second 2; }
    return 204;
}

# proxy_pass の URI が書き換わらない
location /proxy-pass-uri {
    proxy_pass http://127.0.0.1:8080/;
    if ($arg_debug) { }
}

# if を入れた瞬間 try_files が無効化
location /if-try-files {
    try_files /file @fallback;
    if ($true) { }
}

4. “安全な if” の範囲

location /old/ {
    if ($request_uri ~* /$) { return 301 /new/; }
}

5. 代替パターン

用途代替手段
ファイル存在チェックtry_filestry_files $uri $uri/ /index.php?$args;
変数マッチでルーティングmapmap $http_user_agent $is_bot { default 0; ~*bot 1; }
リダイレクト / ステータスreturnreturn 403;
複雑な分岐Lua / Perl / njscontent_by_lua_block { ... }

6. if 使用時のチェックリスト

7. 最近の議論と誤解

「if は evil」という表現が誤解を招くとの指摘があり、現在は「location コンテキストでの if に注意」へと解釈が整理されています。

8. まとめ

参考リンク

この記事が役立ったらぜひシェアしてください!