Saya sudah lama tidak menulis apa pun, jadi mari kita encerkan akhir hari Jumat dengan penelusuran yang sederhana, tetapi tidak selalu jelas, di Nginx .
Server web ini memiliki petunjuk peta yang bagus yang memungkinkan Anda menyederhanakan dan mempersingkat konfigurasi. Inti dari arahan ini adalah memungkinkan Anda membuat variabel baru, yang nilainya bergantung pada nilai satu atau lebih variabel asli. Direktif menjadi lebih kuat saat menggunakan ekspresi reguler, tetapi pada saat yang sama dilupakan tentang satu poin penting. Kutipan dari manual:
Karena variabel hanya dievaluasi pada saat penggunaan, bahkan sejumlah besar deklarasi variabel peta itu sendiri tidak menimbulkan overhead pemrosesan kueri tambahan.
Dan di sini penting tidak hanya bahwa "peta tidak memerlukan biaya tambahan untuk memproses permintaan", tetapi juga bahwa "variabel dihitung hanya pada saat penggunaan".
Seperti yang Anda ketahui, konfigurasi Nginx sebagian besar bersifat deklaratif. Ini juga berlaku untuk petunjuk peta , dan, meskipun terletak dalam konteks http , itu tidak dievaluasi sampai permintaan diproses. Artinya, saat menggunakan variabel yang dihasilkan dalam konteks server, lokasi, jika , dll. kami "mengganti" bukan hasil akhir penghitungan, tetapi hanya "rumus" yang akan digunakan untuk menghitung hasil ini pada waktu yang tepat. Tidak ada masalah dalam konfigurasi ini sampai kita menggunakan ekspresi reguler. Yaitu ekspresi reguler dengan pilihan. Lebih tepatnya, ekspresi reguler dengan pilihan tanpa nama. Lebih mudah untuk menunjukkan dengan contoh.
Misalkan kita memiliki domain example.com dengan banyak subdomain tingkat 3 , seperti ru.example.com, en.example.com, de.example.com , dll., Dan kita ingin mengalihkannya ke subdomain baru ru.example. org, en.example.org, de.example.org , dll. Alih-alih menjelaskan ratusan baris pengalihan, kami akan melakukan ini:
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;
}
Di sini kami secara keliru mengharapkan bahwa ketika meminta ru.example.com, regex akan dihitung di peta dan, oleh karena itu, ketika masuk ke lokasi , variabel $ redirect_host akan berisi nilai ru.example.org , tetapi kenyataannya ini bukan itu masalahnya:
$ 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
karena alokasi kami yang tidak disebutkan namanya $ 1 akan mendapatkan hasil bernama $ domainlevel3 . Artinya, Anda perlu menggunakan pilihan bernama di kedua ekspresi reguler:
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;
}
}
Dan sekarang semuanya berfungsi seperti yang diharapkan:
$ GET -Sd ru.example.com GET http://ru.example.com 301 Moved Permanently GET https://ru.example.org/