Алгоритм выбора location в Nginx
root VS alias
location /ks/ { root /opt/images/; } # /opt/images/ks
location /ks/ { alias /opt/images/; } # /opt/images
С одним уровнем вложенности
- Вначале будет искаться равенство (=). Оно имеет высший приоритет.
- Потом будет искаться максимальный по длине префиксный location (( ) или (^~)), после чего будет проверено, есть ли на найденном location модификатор приоритета (^~), и если он есть, то будет возвращён этот location.
- Потом будут проверяться регулярные выражения ((~) и (~*)) сверху вниз. При совпадении будет возвращён первый location из них.
- Потом вернётся тот префиксный location, который мы нашли до этого.
С вложенными location
Стартуем с верхнего уровня.
Если на текущем уровне выполняется равенство (, поиск прекращается — это и будет результат, т. к. такой location не может иметь никаких других вложенных location.
В противном случае ищем на текущем уровне самый большой префиксный location 1).
Если такой префиксный location существует, то делаем его текущим уровнем и переходим к п. 2.
В противном случае выходим из цикла.
Мы вышли из цикла. На данный момент мы нашли «самый большой» префиксный location, но не думайте, что это самый большой из всех. Пример:
location /abc { location /abcdefghi { … } } location /abcdef { … }
В данном примере мы перейдём в /abcdef, т. к. на его уровне он переборол более короткий /abc. Но по факту существуют location и больше него. Теперь в найденном location мы ищем первый верный regexp. При нахождении поиск полностью прекращается. Обратите внимание: в этом пункте мы по факту ищем regexp на самом нижнем уровне, а не на верхнем, как многие могли бы подумать. Т. е. поиск regexp идёт снизу, а не сверху (но внутри одного уровня идёт сверху, а не снизу). Далее, если ничего не найдено, поднимаемся на один уровень вверх и аналогично ищем первый regexp, но в этот раз уже только при условии, что location, в котором мы были до этого, не имел метки (^~). Повторяем этот пункт до тех пор, пока подниматься будет некуда. При этом нужно иметь ввиду: Даже если какой-то из уровней имеет метку (^~), это не значит, что мы не осуществляем подъём. Подъём осуществляется всегда, но если более нижний уровень имел метку (^~), то на текущем уровне поиск regexp'ов не проводится. Возможности запретить проверку regexp в самом нижнем уровне нет — для этого нужно создать ещё один вложенный уровень. А вот запретить проверку regexp на нулевом уровне можно — для этого location первого уровня (который находится на нулевом уровне) должен иметь метку (^~). Мы сделали подъём по дереву, но так и не нашли ни одного regexp. Раз regexp не найден, возвращаем «почти самый большой» префиксным location, который был найден ранее. Готово.