random_index
Maxim Dounin
mdounin на mdounin.ru
Чт Ноя 3 18:12:24 UTC 2011
Hello!
On Thu, Nov 03, 2011 at 09:35:53PM +0300, ola wrote:
> Здравствуйте, Maxim.
>
> Вы писали 3 ноября 2011 г., 19:31:04:
>
> >> Помогите, пожалуйста, разобраться с random_index.
> >>
> >> server {
> >> listen 127.0.0.1:80;
> >> server_name localhost;
> >> error_log logs/error.log debug;
> >>
> >> location / {
> >> root /common/example.org/www;
> >> index index.html;
> >> }
> >>
> >> location ~ ^/banner(\d+)/$ {
> >> alias /common/example.org/adv/$1/;
> >> random_index on;
> >> }
> >> }
> >>
> >> При запросе /banner2/ получается 404-я ошибка, nginx пытается отдать
> >> файл /common/example.org/www/banner2/1.html
> >>
> >> Если использовать location ~ ^/banner(\d+)/ {} (без завершающего $),
> >> то nginx делает 10 внутренних редиректов и "Redirection limit of 10
> >> URL's reached"
>
> > Если в директиве alias используются переменные, то она задаёт
> > полный путь к файлу, который надо использовать.
> Максим, объясните, пожалуйста, поподробнее. Я ж вроде и использую
> полный путь.
Значение "/common/example.org/adv/$1/" задаёт путь к каталогу, а
не к конкретному файлу.
> > Должно сработать как-то так:
>
> > location ~ ^/banner(?<number>\d+)/(?<file>.*) {
> > alias /common/example.org/adv/$number/$file;
> > random_index on;
> > }
> Это немного не то. Если использовать ваш вариант, то получается что
> рандомные имена файлов (?<file>.*) надо генерить на бекенде. А
> хотелось бы использовать nginx для этой задачи.
Нет, не надо. Модуль random index, увидив запрос к каталогу,
сгенерирует внутренний редирект на случайный файл из каталога.
Дальше нужно, чтобы этот перенаправленный запрос кто-то обработал.
В конфиге, который вы привели, всё происходит так:
1. Запрос "/banner2/" попадает в "location ~ ^/banner(\d+)/$".
2. Модуль random index делает внутренний редирект на "/banner2/1.html".
3. Запрос "/banner2/1.html" попадает в "location /", пытается
открыть файл /common/example.org/www/banner2/1.html (root + uri) и
возвращает 404, т.к. такого файла нет.
Если написать, как вы пытались, "location ~ ^/banner(\d+)/"
аналогичного содержания, то будет так:
1, 2 - то же самое.
3. Запрос "/banner2/1.html" попадает в "location ~ ^/banner(\d+)/".
Тут nginx попытается открыть путь, заданный директивой alias (ибо
она с переменными), а именно "/common/example.org/adv/2/".
Обнаружит, что это - не файл, а каталог, и отдаёт 301 redirect с
добавлением ещё одного '/' в конец uri. Дальше браузер делает ещё
один запрос, и цикл повторяется пока браузеру не надоест.
> По дебаг-логу видно что нгинкс сначала преобразовывает алиас, затем из
> списка файлов в получившейся директории выбирает рандомный, но
> добавляет выбранное имя файла к исходному (текущему?) uri, а не к
> пути, полученному из алиаса. Потом делается внутренний редирект и
> начинается опять поиск нужного дlocation'a.
Да, именно так. И index, и random_index работают по одному и тому
же принципу: ищут подходящий индексный файл и делают внутренний
редирект на него. Это, в частности, позволяет использовать
индексные файлы с отдельной обработкой, e.g. index.php.
Дополнительные детали можно почитать тут:
http://nginx.org/en/docs/http/request_processing.html
> Вот если бы выбранное рандомом имя добавить к преобразованному
> алиасу и остановиться на этом...
> Пробовала написать break; но видимо оно не для internal redirect.
Нужно просто сделать, чтобы получившийся после внутреннего
редиректа запрос правильно обрабатывался. Именно это и делает
предложенный мной конфиг.
Maxim Dounin
Подробная информация о списке рассылки nginx-ru