Деректива Nginx - location с примерами

  • Михаил
  • 12 мин. на прочтение
  • 336
  • 07 Aug 2022
  • 07 Aug 2022

Nginx location — структура в конфигурационном файле Nginx определяющая к URl и запросам какого вида будут применяться описанные правила. Директива location всегда задается внутри блока server конфигурационного файла Nginx. С location используют регулярные выражения, при этом выполняются действия заданные для блока для которого совпадение с  маской самое узкое.

Т.е. под location / будут подпадать все файлы, обрабатываемые сервером, под location ~ \.php будут подпадать только скрипты с расширением .php, опции для корня обрабатываться не будут. Ниже основные случаи будут рассмотрены подробно.

nginx

Директива location служит для установки конфигурации в зависимости от URI-запроса. Синтаксис location в общем виде следующий:

Syntax:   location [=|~|~*|^~] uri { ... }
          location @name { ... }
Context:  server, location

Перед тем, как перейти к более детальному изучению, нужно заметить, что location определяется в контексте server (или в location в случае вложенной директивы), и в одном настраиваемом виртуальном хосте могут использоваться разные конфигурации в зависимости от обрабатываемого сервером URI.

Регулярные выражения в location Nginx:

  • = строковые совпадения, если совпадение с шаблоном обнаружено дальнейшая проверка заканчивается
  • ~ тильда в начале означает, что регистр будет учитываться
  • ~*регулярные вырадения без учета регистра
  • ^~ приоритетное строковое значение, чтобы применились опции требуется совпадение начала выражения — если это каталог, то директивы текущего location будут распространяться на все файлы в нем

Префикс «@» («собака») определяет именованные расположения. Такие location’ы не используются для обработки обычных запросов. Вместо этого они используются для перенаправления запросов (пример №6). Они не могут быть вложенными и содержать в себе вложенные.

Порядок обработки:

  1. = Строковые совпадения. Если найдено, проверка заканчивается. = значит полное совпадение шаблона и проверяемой строки, например = / — заход в секцию будет исключительно для корня, и даже файлы в корне уже сюда не подходят.
  2. ^~ Приоритетное строковое значение. Хотя по-моему было бы правильнее назвать «приоритетным регулярным выражением», поскольку в отличии от = требуется совпадение только начала. ^~ / полностью отключит регулярные выражения для секции server, если нет более точного location без ^~
  3. Строковые значения (/download/). Ищется максимальное совпадение, смотрится только с начала пути. Если нужно совпадение вида /*/download/, то это уже будет п.4, так что в уме можно читать такую запись как /download/* Но на этом проверка не заканчивается!
  4. ~, ~* Регулярные выражения, в порядке определения в конфиге. При совпадении — выполняется этот регэксп, проверка заканчивается. ~ — с учётом регистра, ~* — без.
  5. Если не было найдено подходящей регулярки, используется наибольшее совпадение из п.3.

Принципы обработки location и директивы listen

 

Nginx считывает конфигурацию блоками, они заключены в location, которые находятся в блоке server. Расположение location относительно друг друга не имеет значения, вперед обрабатывается всегда тот, что имеет высший приоритет согласно логике работы Nginx.

server {

location {

}

}

 

server характеризуется адресом, портом и запрашиваемым доменным именем

Они определяются директивой listen. Если один или несколько параметров не указаны используются значения по умолчанию.

Так при отсутствующем адресе будет использован 0.0.0.0, при отсутствующем порте 80 для пользователя root, 8080 для любого другого пользователя.

 

 

Более точное явное совпадение IP адереса и порта обслуживается в первую очередь.
Если и порт и адрес заданы для двух location — идет сравнение server_name.

 

 

При отсутствии server_name, но присутствии IP адреса и порта блок всегда будет выполняться первым даже если в другом location есть server_name, совпадающий с запрашиваемым, но не указан порт или адрес.

 

 

Если сравнение происходит на уровне server_name работает следующая логика:

  • при полном совпадении значений выбирается первое найденное совпадение (example.com)
  • если полного совпадения нет — происходит поиск с учетом * (*xample.com) в начале по маске, выбирается самый длинный server_name
  • если таких нет — происходит поиск с учетом * в конце по маске, выбирается самый длинный server_name (example.*)
  • при отсутствии совпадений начинают рассматриваться регулярные выражения (начинающиеся с ~), первое совпадение запоминается
  • когда ничего из перечисленного не подходит используется default блок

 

 

Nginx location, примеры использования и принципу выбора location

Веб-сервером Nginx location выбирается сравнивая URI поступившего запроса с обозначением location

 

1) с полным URI сравниваются все выражения, не включающие регулярные выражения

2) сначала сверяются все блоки с =

3) если совпадений нет проверяется ^~ и сразу задействуется самый длинный из них

4) не найдя таких Nginx ищет опять же самое длинное совпадение и резервирует результат поиска

5) проверка с учетом регулярных выражений — выбирается первое выражение среди подходящих под самый длинный префикс

6) при отсутствии результата используется блок, зарезервированный на шаге 4

 

Изменить эту логику и заставить какой-то блок обрабатываться вперед остальных проще всего используя = или ^~

 

 

 

Переход в другой location

Перенаправление в другой блок выполняется за счет одной из приведенных ниже директив:

try_files
rewrite
error_page

 

 

Перенаправление за счет try_files

server_name example.com;
root /home/sites/example.com;
location / {
try_files $uri $uri.html $uri/ /none/index.html;
}

location /none {
root /var/sites/new;
}

 

При поступлении запроса к example.com/request Nginx первым делом увидит $uri и поппытается найти location request.

 

Такого нет, далее следует поиск request.html и каталога request. Если таких нет, то запрос переадресуется в резервный location на страницу /none/index.html

 

Веб-сервер выдаст пользователю содержимое /var/sites/new/none/index.html

 

 

За счет rewrite

Запрос к example.com/newrequest/someurl будет обрабатываться location / без какой-либо переадресации

 

server_name example.com;
root /home/sites/example.com;
location / {
rewrite ^/newrequest/(.*)$ /$1;
try_files $uri $uri.html $uri/ /none/index.html;
}

 

return работает также, но используется обычно для переадресации на URL, а не в другой location
Его добавляют, когда нужно перенаправить пользователя на другой домен или другую версию сайта (например без www или с https)

 

 

За счет error_page

Это скорее не редирект, а способ задания собственных страниц ошибок. Перенаправление будет происходить каждый раз когда не найдена запрашиваемая страница

 

location / {
error_page 404 /somefolder/errorpage.html;
}

 

 

 

 

 

Практический пример поясняющие использование Nginx location взятый с официального сайта

Типовая конфигурация для сайта на PHP при которой применяется Nginx с FPM, статика обрабатывается самим веб-сервером, для изображений дополнительно задается кэширование.

 

server {
listen 80;
server_name example.com;
root /data/www;

location / {
index index.html index.php;
}

location ~* \.(gif|jpg|png)$ {
expires 30d;
}

location ~ \.php$ {
fastcgi_pass localhost:9000;

}
}

 

При обращении к /data/www/script.html за отсутствием других совпадений будет выбран location /data/www, если в URL php скрипт он обработается другим блоком и запрос передастся на обработку на порт 9000, на котором работает PHP-FPM.

 

Для изображений будет выбран блок в котором устанавливается заголовок expires, затем запрос обрабатывается тем выражением, которое задано для /, т.е. картинки будут запрашиваться в /data/www, если их там нет возникнет ошибка 404.

 

 

 

 

 

 

Примеры использования location

Пример конфигурации №1. Для корневого URI «/»

location = / {
    # Расположение только для URI /
    # При совпадении дальнейший поиск не осуществляется
}

Пример конфигурации №2. Базовый location

location / {
    # Совпадает с URI всех запросов, т.к. они все начинаются с "/"
    # Но! Если будут найдены соответствия в расположениях
    # с регулярными выражениями или с другим более длинным
    # строковым литералом (например, "/data/"), 
    # то конфигурация для "/" не будет применена.
}

Пример конфигурации №3. Для URI вида «/data/.*»

location /data/ {
    # Это расположение соответствует всем URI, начинающихся с "/data/"
    # и продолжает поиск по оставшимся location'ам.
    # В этом примере регулярные выражения и другие строковые литералы
    # также будут проверены, и "location /data/" будет использован,
    # если более конкретизирующие расположения не удовлетворят искомому ресурсу.
}

Пример конфигурации №4. Для URI вида «/img/.*»

location ^~ /img/ {
    # Соответствует любому URI, начинающемуся с "/img/".
    # Если соответствие установлено - останавливает дальнейший поиск,
    # не проверяя регулярные выражения, т.к. используется
    # префикс ^~ "крышечка/циркумфлекс тильда".
}

Пример конфигурации №5. Для графических форматов

location ~* \.(png|ico|gif|jpg|jpeg)$ {
    # Данное расположение соответствует всем запрашиваемым URI,
    # оканчивающихся ".png", ".ico", ".gif", ".jpg" или ".jpeg".
    # При этом надо заметить, что запросы внутри расположения "/img/"
    # будут обработаны в location из примера №4
    # Т.е., если расположения из примеров №4 и №5 разместить в таком же
    # порядке в реальном конфиге, то до этого расположения ресурсов 
    # дойдут только те картинки, которые лежат вне расположения "/img/"
}

Пример конфигурации №6. Именованный location

location / {
    error_page 404 = @fallback;
}

location @fallback {
    # Если при внутреннем перенаправлении не нужно менять URI,
    # то можно передать обработку ошибки в именованный location
}

Пример конфигурации №7. Выделение переменной

location ~ ^/a/(?[a-zA-Z]+) {
   # Тут можно использовать переменную $myvar,
   # которая представляет из себя строку из латиницы
   if ($myvar = "sth") { ... }
}

Примеры реальных nginx location’ов

Anti-hotlinking

Директива location для Anti-hotlinking (борьбы с использованием ресурсов с вашего сервера на сторонних ресурсах. Такой способ использования ваших сетевых ресурсов называется hotlinking). Такое поведение хитрых разработчиков может заметно увеличить нагрузку на ваш сервер. Конфигурация:

location ~ \.(gif|png|jpe?g)$ {
    valid_referers none blocked mywebsite.com *.mywebsite.com;
    if ($invalid_referer) {
       return 403;
    }
}

Запрет на скрипты внутри директорий

Следующий пример — запрет на скрипты в разрешённых для записи директориях:

location ~* /(images|cache|media|logs|tmp)/.*\.(php|pl|py|jsp|asp|sh|cgi)$ {
    error_page 403 /403.htm;
    return 403;
}

Включение autoindex

В следующем примере location используется для включения autoindex в nginx (Разрешение на вывод листинга каталога):

location /list_dir {
    autoindex on;
    autoindex_exact_size off;
    autoindex_localtime on;
}}

Проксирование Nginx на другой IP

server {
    listen   80;
    server_name домен;
    access_log off;
    error_log off;
    location / {
	# remote HTTP server
        proxy_pass http://IP:Порт;
	proxy_redirect http://IP:Порт /;
	proxy_set_header Host $host;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header X-Forwarded-Proto $scheme;
	proxy_set_header X-Real-IP $remote_addr;
        proxy_connect_timeout 600;
    }
}