Pull to refresh

Comments 21

почему же тогда пришлось переместить этот кусок
location ~ \.html$ {
try_files $uri =404;
}

над этим
location ~ / {
rewrite . /index.php last;
}

иначе всегда отрабатывал location ~ / при запросе к *.html файлам
Перечитайте статью. У Вас один уровень вложенности. В пределах одного уровня вложенности поиск регулярных выражений происходит сверху вниз.

Цитата из статьи:
(но внутри одного уровня идёт сверху, а не снизу).

Но в пределах нескольких уровней мы вначале находим префиксный location, а потом делаем обратный подъём по дереву.
у меня как-то не сошлось понимание написанного:
1. Стартуем с верхнего уровня.
2.…
3. В противном случае ищем на текущем уровне самый большой префиксный location ((   ) или (^~)).

«текущим» для этого простого конфига является самый верхний уровень. Тогда почему игнорируется пункт №3?
Всё верно, на первой итерации текущий уровень — это верхний. Но ведь в третьем пункте сказано:
Если такой префиксный location существует, то делаем его текущим уровнем и переходим к п. 2.

В общем, я не понимаю Ваш вопрос. Возможно, Вам стоит перечитать алгоритм. Либо мне попытаться объяснить его более просто, но способов упрощения я пока не знаю.

Тогда почему игнорируется пункт №3?
Где он игнорируется?
Если уровней всего один, то какой location будет выбран первым? Вот это, если можно, хочется услышать дополнительно в алгоритме.
Если уровней один, то всё слишком просто.

  1. Вначале будет искаться равенство
  2. Потом будет искаться максимальный префиксный location, после чего будет проверено, есть ли на нём модификатор приоритета
  3. Потом regexp сверху вниз
  4. Потом вернётся тот префиксный location, который мы нашли до этого

Я сейчас добавлю это в статью, т. к. не все пишут конфиги с вложенными location, а без них алгоритм можно описать значительно проще. Просто я думал, что это уже итак все знают, и интересен был более общий случай.
Добавил частный случай с одним уровнем вложенности.
Это привлечёт внимание тех, кто ищет с одним уровнем вложенности. Заодно разберутся и с тем, когда несколько уровней.
Спасибо, думаю, Вы правы. Вначале поставил описание частного случая, а потом уже описание общего случая с вложенными location. Многим вложенные уровни вообще могут быть не нужны, и они сюда пришли за простым алгоритмом, а в итоге получили супер-навороченный алгоритм, в котором нереально разобраться.
Ну и на всякий случай скопирую пример из статьи, чтобы было понятнее.

location ~ \.php$ {
	…
}

location /posts/ {
	location ~ (.*)_2x(\.[a-z]+)$ {
		try_files $uri $1$2 =404;
	}
}

Здесь при запросе /posts/*** в случаях, когда выражение подходит и под первый regexp-location, и под второй regexp-location, приоритет будет отдан второму regexp-location'у, даже несмотря на то, что он идёт после первого.
Потому что второй локейшен не regexp-location, а префиксный.
Документация гласит:

location можно задать префиксной строкой или регулярным выражением. Регулярные выражения задаются либо с модификатором “~*” (для поиска совпадения без учёта регистра символов), либо с модификатором “~” (с учётом регистра). Чтобы найти location, соответствующий запросу, вначале проверяются location’ы, заданные префиксными строками (префиксные location’ы).
Я имел ввиду второй regexp (среди location'ом он третий по счёту).

А насчёт документации — там не говорится ничего чётко. Вот цитата, которую Вы привели:
Чтобы найти location, соответствующий запросу, вначале проверяются location’ы, заданные префиксными строками

Ну вот нашли мы префиксный location, а что дальше? И имелся ли ввиду поиск префиксного location на текущем уровне или сразу на всех? На эти два вопроса и даёт ответ данная статья. А вопросы то очень важные.
Ну вот нашли мы префиксный location, а что дальше?

А дальше забываем про все location, что "выше". Нет их.
Теперь есть только то, что есть здесь и ниже.
На мой взгляд, такой подход все объясняет (и упрощает).


И имелся ли ввиду поиск префиксного location на текущем уровне или сразу на всех?

На текущем.
Боюсь, здесь люди попадают в ловушку того, что сами себя перемудрили.
Надо просто считать так: верхние уровни ничего не знают про нижние, а нижние — ничего не знают про верхние: "вот есть один уровень, посмотрим, куда упадет запрос".

К сожалению, официальной документации нельзя доверять

Почему? Что там не так?

Ну как минимум там даже не потрудились привести алгоритм выбора location при наличии вложенных location. А то, что приведено, не сказано, что это для частного случая, когда вложенных location нет. Нет, там и не сказано, что это для общего случая, но блин… :) Это немного ввод в заблуждение.

Черт его знает, мне все понятно, но я пользовался вложенными location-ами еще когда они были задокументированы только на языке С, так что мне сложно судить, насколько оно может быть непонятно. Если знаете, как написать лучше — напишите, патчи на документацию они принимают.

В пункте 2 лучше объяснить подробнее что такое префиксный location, чтобы избежать путаниц.
Фактически возвращается самый длинный подходящий не регулярный location, если такого нет — идёт поиск по регулярным сверху вниз.
Предполагается, что читающий уже знает, что такое префиксный location. Это location (   ) или (^~).
Хотели как лучше, а получилось как всегда.
Раз уже замутили схему, где у тебя половина конфига рассматривается как попало, а вторая половина по расположению в конфиге, то могли бы уж тестирование локейшенов сделать. А то сейчас единственный способ — это запуск в debug режиме, прогон запроса ручками и чтение портянки логов.

Кучу лет пользуюсь nginx, и только сейчас узнал, что location могут быть вложенными! С одной стороны ни разу не было необходимости в таком, с другой предупрежден — значит вооружен. Спасибо!

Sign up to leave a comment.

Articles