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

Web2026-09-20TryQuickToolBox

Вы наверняка правили конфиг Nginx, перезагружали его и недоумевали, почему ваш блок location словно не применяется. Может быть, запрос к статическому файлу попадает в PHP-обработчик, или маршрут API поглощается catch-all. Виновником часто оказывается алгоритм сопоставления location в Nginx — он не так прост, как кажется.

В этом руководстве мы разберём, как Nginx выбирает блок location, с реальными примерами, которые вы можете проверить. К концу вы будете точно знать, какой блок побеждает и почему.

Как работает сопоставление location в Nginx

Когда приходит запрос, Nginx сравнивает URI со всеми определёнными блоками location. Процесс сопоставления следует определённому порядку:

  1. Точное совпадение (=) — высший приоритет. Если найдено, Nginx останавливается и использует его.
  2. Самое длинное префиксное совпадение — Nginx запоминает самый длинный совпавший префиксный location.
  3. Совпадение с регулярным выражением (~ или ~*) — проверяются в порядке появления. Первое совпавшее регулярное выражение побеждает, переопределяя префиксное совпадение (если не используется ^~).
  4. Префиксное совпадение с ^~ — если самый длинный совпавший префикс имеет ^~, Nginx пропускает проверку регулярных выражений и использует его.
  5. Если ни одно регулярное выражение не совпало, используется самое длинное префиксное совпадение.

Это основной алгоритм. Давайте посмотрим его в действии.

Модификаторы location: краткая справка

МодификаторСинтаксисТип совпаденияПриоритет
=location = /pathТочноеНаивысший
^~location ^~ /pathПрефиксное (без regex)Высокий
~location ~ \.php$Regex (с учётом регистра)Средний
~*location ~* \.(jpg|png)$Regex (без учёта регистра)Средний
нетlocation /pathПрефиксноеНизший

Реальный пример 1: Статические файлы против PHP

Рассмотрим эту распространённую конфигурацию:

server {
    listen 80;
    server_name example.com;

    location / {
        root /var/www/html;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }
}

Запрос к /index.php совпадает с регулярным выражением \.php$, поэтому он уходит в PHP-FPM. Запрос к /logo.png не совпадает с регулярным выражением, поэтому он возвращается к префиксу / и отдаёт статический файл. Просто, правда?

Но что если вы хотите отдавать /uploads/photo.php как статический файл (возможно, на самом деле это изображение)? Вы можете добавить точное совпадение:

location = /uploads/photo.php {
    root /var/www/html;
}

Теперь это точное совпадение имеет приоритет над регулярным выражением.

Реальный пример 2: Маршрутизация API с префиксом и regex

Предположим, у вас есть API по пути /api/, и вы хотите проксировать все запросы к бэкенду, кроме проверки работоспособности, которая возвращает статический ответ.

location = /api/health {
    return 200 "OK";
}

location /api/ {
    proxy_pass http://backend;
}

location ~ ^/api/v[0-9]+/special {
    proxy_pass http://special-backend;
}

Проследим /api/health: точное совпадение побеждает, возвращает 200. Для /api/users: нет точного, нет regex (не совпадает с special), поэтому используется самый длинный префикс /api/. Для /api/v1/special: регулярное выражение совпадает, поэтому оно переопределяет префикс и запрос идёт к special-backend.

Это демонстрирует, как regex может переопределить префиксное совпадение. Если вы хотите, чтобы префикс всегда побеждал, используйте ^~ вместо этого.

Реальный пример 3: Сила ^~

Представьте, что у вас есть директория /static/ с файлами, которые никогда не должны обрабатываться PHP, даже если они заканчиваются на .php. Использование ^~ гарантирует, что Nginx не проверяет regex-локации.

location ^~ /static/ {
    root /var/www/html;
}

location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}

Запрос к /static/script.php совпадает с префиксом ^~ /static/. Благодаря ^~ Nginx пропускает проверку regex и отдаёт файл напрямую. Без ^~ регулярное выражение совпало бы, и PHP-FPM выполнил бы его — потенциальный риск безопасности.

Распространённые ошибки и как их избежать

Отладка сопоставления location

Если вы не уверены, какой location используется, включите отладочное логирование в Nginx. Добавьте error_log /var/log/nginx/error.log debug; в ваш server-блок, перезагрузите и проверьте лог. Вы увидите строки вроде test location: "/api/users" и using configuration "/api/".

Как вариант, временно используйте return 200 "matched: /api/"; в каждом location, чтобы увидеть, какой из них отвечает.

FAQ

Каков порядок приоритета модификаторов location в Nginx?

Точное совпадение (=) — наивысший, затем самый длинный префикс с ^~, затем regex (~ или ~*) по порядку, затем самое длинное префиксное совпадение без ^~.

Может ли regex-локация переопределить префиксную локацию?

Да, если только префиксная локация не использует ^~. Regex-локации проверяются после самого длинного префиксного совпадения, и если regex совпадает, он имеет приоритет над обычным префиксом.

Как настроить location только для конкретного файла?

Используйте точное совпадение с =, например, location = /favicon.ico. Это гарантирует совпадение только для этого точного URI.

Освойте свою конфигурацию Nginx

Понимание сопоставления location — ключ к надёжной настройке Nginx. Проверяйте свои конфиги с помощью nginx -t и используйте отладочные логи при сомнениях. Если вы работаете с логами Nginx и вам нужно анализировать шаблоны трафика, попробуйте наш Nginx Log Analyzer, чтобы быстро парсить и визуализировать ваши логи.