[Настройка Linux, Системное администрирование, Nginx, *nix] Немного об использовании regex в map nginx
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Давно ничего не писал, поэтому разбавим конец пятницы простыми, но не всегда очевидными иcканиями в Nginx.В этом веб-сервере есть замечательная директива map, которая позволяет существенно упростить и сократить конфиги. Суть директивы в том, что она позволяет создать новую переменную, значение которой зависит от значений одной или нескольких исходных переменных. Ещё большую силу директива приобретает при использовании регулярных выражений, но при этом забывается, об одном важном моменте. Выдержка из мануала:
Поскольку переменные вычисляются только в момент использования, само по себе наличие даже большого числа объявлений переменных map не влечёт за собой никаких дополнительных расходов на обработку запросов.
И здесь важным является не только, то что "map не влечёт за собой никаких дополнительных расходов на обработку запросов", а и то, что "переменные вычисляются только в момент использования".Как известно, конфиг Nginx, в основном, декларативен. Это касается и директивы map, и, не смотря на то, что она расположена в контексте http, её вычисление не происходит до момента обработки запроса. То есть при использовании результирующей переменной в контекстах server, location, if и т.п. мы "подставляем" не готовый результат вычисления, а лишь "формулу" по который этот результат будет вычислен в нужный момент. В этой конфигурационной казуистике не возникает проблем до того момента, пока мы не используем регулярные выражения. А именно регулярные выражения с выделениями. А ещё точнее, регулярные выражения с неименованными выделениями. Проще показать на примере. Допустим у нас есть домен example.com с множеством поддоменов 3-го уровня, а-ля ru.example.com, en.example.com, de.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 произойдет вычисление регулярки в map и, соответственно, попав в location переменная $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/
===========
Источник:
habr.com
===========
Похожие новости:
- [Тестирование IT-систем, Python, Программирование] Как протестировать блокноты Jupyter с помощью pytest и nbmake (перевод)
- [Системное администрирование, IT-компании] Как работает Team Viewer
- [Информационная безопасность, Системное администрирование, Сетевые технологии] Использование и настройка локального API CrowdSec
- [Системное администрирование, Софт] SaaS и ALEPIZ: мониторинг и управление инфраструктурой
- [Настройка Linux, *nix, Разработка под Linux] Gentoo/Arch/LFS как путь в мир Linux
- [Криптография, Программирование, *nix, Автомобильные гаджеты] Тесла верит своим Богам! Так она находит путь
- [Системное администрирование, Браузеры, Софт, IT-компании] Microsoft прекратит поддержку приложения Internet Explorer 11 в Windows 10 с июня 2022 года
- [Системное администрирование, Kubernetes] Антипаттерны деплоя в Kubernetes. Часть 1 (перевод)
- [NoSQL, MongoDB] Иерархия потребностей по Маслоу при разработке документации (перевод)
- [Системное администрирование, Сетевые технологии] Делегирование почтовых папок и отправки писем в Zimbra OSE
Теги для поиска: #_nastrojka_linux (Настройка Linux), #_sistemnoe_administrirovanie (Системное администрирование), #_nginx, #_*nix, #_nginx, #_map, #_regex, #_nastrojka_linux (
Настройка Linux
), #_sistemnoe_administrirovanie (
Системное администрирование
), #_nginx, #_*nix
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 06:40
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Давно ничего не писал, поэтому разбавим конец пятницы простыми, но не всегда очевидными иcканиями в Nginx.В этом веб-сервере есть замечательная директива map, которая позволяет существенно упростить и сократить конфиги. Суть директивы в том, что она позволяет создать новую переменную, значение которой зависит от значений одной или нескольких исходных переменных. Ещё большую силу директива приобретает при использовании регулярных выражений, но при этом забывается, об одном важном моменте. Выдержка из мануала: Поскольку переменные вычисляются только в момент использования, само по себе наличие даже большого числа объявлений переменных map не влечёт за собой никаких дополнительных расходов на обработку запросов.
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; } $ GET -Sd ru.example.com
GET http://ru.example.com 301 Moved Permanently GET https://ru.example.orgru 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 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/ =========== Источник: habr.com =========== Похожие новости:
Настройка Linux ), #_sistemnoe_administrirovanie ( Системное администрирование ), #_nginx, #_*nix |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 06:40
Часовой пояс: UTC + 5