- ブラウザURL入力
- DNS名前→IP
- ルータ経路選択
- ロードバランサ振り分け
- Nginx受け口今ここ
- アプリ処理
- DB保存
受け口に届いたリクエストを、設定のどのブロックが処理するかを決める段です。プロセス構成ではなく設定構文だけを扱います。
まず結論
最長一致した prefix は勝者ではなく「記憶」されるだけの暫定候補です。後から検査される正規表現が一致すれば逆転されます。
正規表現には最長一致も最具体一致もなく、先に書かれた方が勝ちます。第18週のルーティング表と違い、記述順が結果を変えます。
次の設定に `/sel/long/a.jpg` が来ました。どれが使われるでしょうか。 location /sel/long/ { ... } ← prefix(最長一致する) location ~* \.(gif|jpg)$ { ... } ← 正規表現
当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。
prefix の最長一致は、まだ結果ではない
location 選択はよく「上から順に見て最初に当たったもの」と説明されます。これは誤りです。 公式が定める順序はこうです。
- ・`=` の完全一致は①の prefix 検査の中で見つかれば、その場で探索全体を終わらせる(②③④へ進まない)
肝心なのは①です。公式は最長一致した prefix を selected and remembered(選んで記憶する)と書きます。
実機で逆転が起きる
nginx/1.30.4 での実測です。
location /sel/long/ { return 200 "C longer-prefix\n"; }location ^~ /sel/images/ { return 200 "D caret-tilde\n"; }location ~* \.(gif|jpg)$ { return 200 "E regex-first-in-file\n"; }location ~ \.jpg$ { return 200 "F regex-second-in-file\n"; }/sel/long/a.jpg -> E ← 最長prefix C が逆転された/sel/images/a.gif -> D ← ^~ なので正規表現が検査されない/a.gif -> E ← F ではなく、先に書かれた E
/sel/long/a.jpg は prefix /sel/long/ に最長一致します。それでも **E が使われました。**記憶されていた C が正規表現に上書きされたのです。
.jpg には E と F が一致しますが、勝つのは 先に書かれた E。F の方が限定的でも関係ありません。
Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used.
**正規表現に「最長一致」も「最具体一致」も存在しません。**あるのは順序だけです。
`.jpg` に一致する正規表現 location が2つあります。1つ目は `~* \.(gif|jpg)$`、2つ目は `~ \.jpg$` です。より限定的なのは2つ目ですが、選ばれるのはどちらですか。
ルーティング表の最長一致(第18週)
宛先 192.168.1.130 には3行すべてが当てはまり、最も細かい /25 が選ばれます。重要なのは、この判定が行の順序に一切依存しないことです。
行 一致ビット数 結果0.0.0.0/0 0 負ける192.168.1.0/24 24 負ける192.168.1.128/25 25 採用(確定)
nginx の location
`/sel/long/a.jpg` には prefix と正規表現の両方が当てはまります。最長一致するのは prefix ですが、採用されるのは正規表現です。しかも正規表現が2つあれば、先に書かれた方が勝ちます。
候補 土俵 結果/sel/long/ prefix 最長一致 → 記憶(暫定)~* \.(gif|jpg)$ 正規表現 先に書かれている → 採用~ \.jpg$ 正規表現 後に書かれている → 検査されず
どちらも「当てはまる候補が複数あるとき1つを選ぶ」仕組みです。共通している部分はどこまでで、どこから違うでしょうか。
「設定ファイル/表の行を並べ替えたら、結果は変わるか」を両方で考えてみてください。
「`^~` を付けた location は、見つかった瞬間に探索を打ち切る」という説明は正確ですか。
この章のまとめ
- 最長一致した prefix は selected and remembered — 採用ではなく暫定候補。正規表現に逆転されうる。
- 正規表現は出現順に検査され最初の一致で終了。最長一致も最具体一致も無い。
^~が省略を起こすのは「最長一致した prefix が結果的に^~だったとき」。即座に止まるのは=。- 第18週のルーティング表との決定的な違いは、記述順が結果を変えること。
自分の現場で確かめる
読んだだけでは身につきません。手元の環境で実際に見てみてください。
理解度チェック
読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。
「nginxの location は上から順に評価され、最初に当たったものが使われる」という説明の評価として正しいものはどれですか。
用語集(6語)
- prefix location
- 修飾子なし、または `=` `^~` を伴う、前置文字列で定義された location。この土俵では最も長く一致したものが「記憶」される。
- 正規表現 location
- `~`(大文字小文字を区別)/`~*`(区別しない)を伴う location。出現順に検査され最初の一致で終わる。長さや具体性は考慮されない。
- `^~`
- 最長一致した prefix location がこの修飾子を持っていた場合に、正規表現と predicate location を検査しない。「見つかった瞬間に打ち切る」ではない。
- `=`
- URIとの完全一致を定義する修飾子。一致が見つかった時点で探索全体が終了する。入れ子の location を持てない。
- named location (`@name`)
- `@` を前置して定義する location。通常のリクエスト処理には使われず、リクエストの転送先として使われる。入れ子にできない。
- predicate location (`$variable`)
- nginx 1.31.5 で追加された形式。変数の値が空でなく `0` でもないときに一致する。正規表現の後に出現順で検査される。