Nginx で location の判定方法と優先順位を調べる
ここまでにNginxに関して色々記事を書いてきました。
今回は、Nginxの設定の中でrewrite (リダイレクトディレクティブ)の次によく利用する location (ロケーションディレクティブ)を使ってみます。
いくつか例をあげて解説してみましょう。
location ディレクティブの基本
location ディレクティブは、wikiの記載内容は、以下のようになっています。
location [ = | ~ | ~* | ^~ ] uri { ... }
location { } @ name { ... }
このディレクティブは、URIに応じた様々な制御を行うことができます。
このディレクティブで使用できる判定のための修飾子は、以下のようになっています。
- = : 完全一致
- ^~ : 前方検索(正規表現より優先度が上)
- ~ : 正規表現(大文字小文字区別あり)
- ~* : 正規表現(大文字小文字区別なし)
- なし : 前方検索(正規表現より優先度が下)
上記の順番は、処理の優先順でもあります。
つまり、
= : 完全一致 で条件が一致したURIでは、以降のlocation ディレクティブは無視されます。
例えば、以下の設定例で簡単に解説してみましょう。
location = / {
# / のみが条件に一致します。
# 完全一致した場合は、何よりも優先され以降のいかなるチェックも(正規表現であっても)
# チェックされずに終了します。
[ configuration A ]
}
location / {
# / で始まる全てのURIに一致します。
# しかし、正規表現や文字列が長いものが優先的に処理されます。
[ configuration B ]
}
location /documents/ {
# /documents/ で始まる全てのURIに一致します。
# しかし、正規表現のチェックは、続けて処理されます。
# これは、正規表現のチェックで一致しなかった場合のみ、一致したと判断されます。
[ configuration C ]
}
location ^~ /images/ {
# /images/ で始まる全てのURIに一致したら、そこで検索終了となります。
# これは、もしURIがこの条件に一致したら、以降いかなるチェックも(正規表現であっても)
# チェックされないことを意味します。
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
# 末尾が、gif, jpg, or jpeg の場合、一致します。
# しかし、/images/ ディレクトリのすべての要求は、Configuration Dで終了してしまうので
# このディレクティブは無視されます。
[ configuration E ]
}
|
例えば以下のような要求が着た場合、それぞれ以下のような判定となります。
- 要求 : http://example.com/ -> configuration A
- 要求 : http://example.com/index.html -> configuration B
- 要求 : http://example.com/documents/document.html -> configuration C
- 要求 : http://example.com/images/1.gif -> configuration D
- 要求 : http://example.com/documents/1.jpg -> configuration E
location ディレクティブの具体例
location ディレクティブの具体的な例をあげて簡単に解説してみます。
ディレクトリの判定順位例
location ディレクティブでは、上記のように色々な判定を行うことができます。
ここでは、同じディレクトリを判定するにも様々な設定があることを簡単に解説してみます。
以下の例は、すべて 条件として
要求 : http://example.com/sample/test.html は、ヒットしますが、実際に処理されるのは、configuration C になります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| location /sample/ {
# /sample/ で始まる全てのURIに一致します。
# しかし、以降の正規表現や文字列が長いものが優先的に処理されます。
[ configuration A ]
}
location ~ ^/sample/ {
# /sample/ で始まる全てのURIに一致します。
# しかし、以降の ^~ が優先的に処理されます。
[ configuration B ]
}
location ^~ /sample/ {
# /sample/ で始まる全てのURIに一致します。
# これは、もしURIがこの条件に一致したら、以降いかなるチェックも(正規表現であっても)
# チェックされないことを意味します。
[ configuration C ]
}
|
上記の例は、同時には設定できません。仮に設定した場合、以下のように二重にlocationディレクティブが設定されている由のエラーが出力されます。
nginx: [emerg] duplicate location "/sample/" in .../conf/nginx.conf:11
|
上記の例でいうと、
location /sample/ {
location ^~ /sample/ {
は、同じlocationディレクティブと判断されます。
^~ の有無は、検索条件に違いがないので同じ・・という解釈だと思います。(ソースコードを追ったわけではないので想像です。)
ちなみに、
location ~ /sample/ {
location ~* /sample/ {
は、違いlocationディレクティブと判断されます。
検索条件が違うからでしょうね。(ソースコードを追ったわけではないので想像です。)
画像ファイルの判定例
location ディレクティブでは、上記のように色々な判定を行うことができます。
ここでは、画像ファイルの判定方法をディレクトリと拡張子でそれぞれ判断した例を簡単に解説してみます。
以下の例は、すべて 条件として
要求 : http://example.com/image/sample.jpg は、ヒットしますが、実際に処理されるのは、configuration B になります。
1
2
3
4
5
6
7
8
9
| location /image/ {
# /image/ で始まる全てのURIに一致します。
# しかし、以降の正規表現や文字列が長いものが優先的に処理されます。
[ configuration A ]
}
location ~* \.(gif|jpg|jpeg)$ {
# 末尾が、gif, jpg, or jpeg の場合、一致します。
[ configuration B ]
}
|
しかし、以下のように、判定に ^~ を使用すると ^~なし と全く同じ検索条件でありながら、優先順が正規表現以上になります。
要求 : http://example.com/image/sample.jpg は、いずれもヒットしますが、実際に処理されるのは、configuration C になります。
1
2
3
4
5
6
7
8
9
10
11
| location ~* \.(gif|jpg|jpeg)$ {
# 末尾が、gif, jpg, or jpeg の場合、一致します。
# しかし、以降の ^~ が優先的に処理されます。
[ configuration B ]
}
location ^~ /image/ {
# /sample/ で始まる全てのURIに一致します。
# これは、もしURIがこの条件に一致したら、以降いかなるチェックも(正規表現であっても)
# チェックされないことを意味します。
[ configuration C ]
}
|
検索手法が同じ場合でいずれも検索条件に一致する場合は、書いた順で優先順位が決定します。
以下の例は、いずれも正規表現の大文字小文字区別なしのパターンです。
要求 : http://example.com
/image/sample.jpg は、いずれもヒットします。
この場合、先に記述されている configuration A が処理されます。
1
2
3
4
5
6
7
8
| location ~* /image/ {
# /image/ で始まる全てのURIに一致します。
[ configuration A ]
}
location ~* \.(gif|jpg|jpeg)$ {
# 末尾が、gif, jpg, or jpeg の場合、一致します。
[ configuration B ]
}
|
逆に
1
2
3
4
5
6
7
8
| location ~* \.(gif|jpg|jpeg)$ {
# 末尾が、gif, jpg, or jpeg の場合、一致します。
[ configuration B ]
}
location ~* /image/ {
# /image/ で始まる全てのURIに一致します。
[ configuration A ]
}
|
と記述すれば、 configuration B が処理されます。当たり前?ですかね。
文字数の違いによる判定例
location ディレクティブでは、検索手法が同じ場合でいずれも検索条件に一致する場合は、書いた順で優先順位が決定すると書きました。
ただし、検索条件が前方検索の場合は、検索文字数によって判断されます。
以下の例は、すべて 条件として
要求 : http://example.com/image/sample.jpg は、ヒットしますが、実際に処理されるのは、configuration B になります。
1
2
3
4
5
6
7
8
9
| location /image/ {
# /image/ で始まる全てのURIに一致します。
# しかし、以降の文字列が長いものが優先的に処理されます。
[ configuration A ]
}
location /image/s {
# /image/s で始まる全てのURIに一致します。
[ configuration B ]
}
|
この条件は、前方検索に限ります。
例えば、以下のように正規表現での検索の場合は、やっぱり、書いた順で処理されます。
以下の例は、いずれも正規表現の大文字小文字区別なしのパターンで、後者が検索する文字列としては多いです。
要求 : http://example.com
/image/sample.jpg は、いずれもヒットします。
この場合、先に記述されている configuration A が処理されます。
1
2
3
4
5
6
7
8
| location ~* \.(gif|jpg|jpeg)$ {
# 末尾が、gif, jpg, or jpeg の場合、一致します。
[ configuration A ]
}
location ~* ^/image/.*\.(gif|jpg|jpeg)$ {
# /image/ の配下で 末尾が、gif, jpg, or jpeg の場合、一致します。
[ configuration B ]
}
|
前方検索と正規表現では、先にも書きましたが、やっぱり、正規表現が優先されます。
要求 : http://example.com/image/sample.jpg は、いずれもヒットします。
この場合、正規表現である configuration A が処理されます。
1
2
3
4
5
6
7
8
| location ~* \.(gif|jpg|jpeg)$ {
# 末尾が、gif, jpg, or jpeg の場合、一致します。
[ configuration A ]
}
location /image/sample.jpg {
# /image/sample.jpg で始まる全てのURIに一致します。
[ configuration B ]
}
|
location /image/sample.jpg
は、文字数も多く完全に一致するものの、前方検索なので優先順位は、正規表現より下になります。
このようにlocation ディレクティブは、いろいろな判定を行って、いろんな処理パターンを設定することができます。
また、location ディレクティブは、location ディレクティブの中でも設定できますから、より細かい条件を判定することもできます。
ただ、パッと見た感じでは、PERLに精通されている方以外は、ちょっとわかりづらいかもしれません。
でも、うまく使いこなせれば、かなり込み入った処理も行えます。Nginxのディレクティブの中でも是非とも理解しておきたいディレクティブの一つです。
しっかり使いこなましょ。
ご利用のブラウザは、広告ブロック(AdBlockなど) が適用となっていませんか?
このサイトでは、コンテンツの一部が非表示、あるいは、コメント、お問い合わせの投稿ができない、検索ができないことがあります。
関連記事 :
コメントを投稿 :