nginxのifに要注意

こんにちは。寺岡です。

最近WEBサーバにnginxを利用することが多いのですが、
その時にハマったポイントをご紹介します。

nginx には ifディレクティブがあり、条件によって設定や変数を切り替えることができます。
このifディレクティブはかなりの曲者で、一般的な感覚とは異なる挙動をします。

皆さんは、以下の設定でどんなヘッダが出力されると思いますか?

一般的な感覚だと、X-First: 1とX-Second: 2が出力されそうな気がします。
当然そうなるんだとろうと思って実行してみると……。

驚いたことに、出力されるのはX-Second: 2のみとなります。

実はこのifディレクティブ、本家でも IfIsEvil なんて注意されていたりします。
設定次第ではSIGSEGVが発生する場合もあるので要注意です。

挙動の詳細については下のリンク先で詳しく説明されています。
How nginx "location if" works

正確に理解できているか自信はありませんが、おそらく以下のようなルールになっていると思われます。

  • if はrewirteフェーズに上から順に実行される
  • add_header等のcontent handlerと呼ばれる種類の定義は、親子関係を持つブロック間で継承される
  • location内にifがある場合、最も深いブロックのcontent handlerが適用される(同一階層の場合は下に記述されたものが優先される)
  • returnやbreakがある場合、rewirteフェーズを終了し、その時点で有効なcontent halderが適用される

この挙動はlocationコンテキスト内にifディレクティブを記述した場合に発生するようです。
ファイルの存在有無で挙動を変えたい場合は try_files を活用すれば何とかなりますので、
よほどの理由がない限りlocation内のifディレクティブは禁止したほうが良いでしょう。

Comments are closed, but you can leave a trackback: Trackback URL.