私は長い間何も書いていなかったので、金曜日の終わりをNginxでの単純な、しかし必ずしも明白ではない検索で薄めましょう。
このWebサーバーには、構成を大幅に簡素化および短縮できるすばらしいマップディレクティブがあります。ディレクティブの本質は、新しい変数を作成できることです。その値は、1つ以上の元の変数の値に依存します。正規表現を使用すると、ディレクティブはさらに強力になりますが、同時に1つの重要な点について忘れられます。マニュアルからの抜粋:
変数は使用時にのみ評価されるため、マップ変数の宣言自体が多数ある場合でも、追加のクエリ処理のオーバーヘッドは発生しません。
そしてここで重要なのは、「マップはリクエストを処理するための追加コストを必要としない」だけでなく、「変数は使用時にのみ計算される」ことです。
ご存知のように、Nginx構成はほとんど宣言型です。これはmapディレクティブにも当てはまり、httpコンテキストにあるにもかかわらず、リクエストが処理されるまで評価されません。つまり、結果の変数をコンテキストサーバー、場所、ifなどで使用する場合です。計算の最終結果ではなく、この結果が適切なタイミングで計算される「式」のみを「代入」します。正規表現を使用するまで、この構成の決疑論に問題はありません。つまり、選択を伴う正規表現。より正確には、名前のない選択を含む正規表現。例を示す方が簡単です。
ru.example.com、en.example.com、de.example.comなどの多くの第3レベルのサブドメインを持つドメインexample.comがあり、それらを新しいサブドメインru.exampleにリダイレクトするとします。 org、en.example.org、de.example.orgなど。数百行のリダイレクトを説明する代わりに、次のようにします。
map $host $redirect_host {
default "example.org";
"~^(\S+)\.example\.com$" $1.example.org;
}
server {
listen *:80;
server_name .example.com;
location / {
rewrite ^(.*)$ https://$redirect_host$1 permanent;
}
ここでは、ru.example.comをリクエストすると、正規表現がマップで計算されるため、場所に到達すると、$ redirect_host変数にru.example.orgの値が含まれると誤って予想していましたが、実際にはそうではありません:
$ GET -Sd ru.example.com GET http://ru.example.com 301 Moved Permanently GET https://ru.example.orgru
, ru.example.orgru. - , " " rewrite .
- regexp map , , :
map $host $redirect_host {
default "example.org";
"~^(\S+)\.example\.com$" $1.example.org;
}
server {
listen *:80;
server_name .example.com;
location / {
return 301 https://$redirect_host$request_uri;
}
}
, ( ).
map:
map $host $redirect_host {
default "example.org";
"~^(?<domainlevel3>\S+)\.example\.com$" $domainlevel3.example.org;
}
server {
listen *:80;
server_name .example.com;
location / {
rewrite ^(.*)$ https://$redirect_host$1 permanent;
}
}
:
$ GET -Sd ru.example.com GET http://ru.example.com 301 Moved Permanently GET https://ru.example.orgru
名前のない割り当て$ 1は、名前の付いた$ domainlevel3の結果を取得するためです。つまり、両方の正規表現で名前付き選択を使用する必要があります。
map $host $redirect_host {
default "example.org";
"~^(?<domainlevel3>\S+)\.example\.com$" $domainlevel3.example.org;
}
server {
listen *:80;
server_name .example.com;
location / {
rewrite ^(?<requri>.*)$ https://$redirect_host$requri permanent;
}
}
そして今、すべてが期待どおりに機能します:
$ GET -Sd ru.example.com GET http://ru.example.com 301 Moved Permanently GET https://ru.example.org/