Перейти к содержанию

Использование несуществующей группы захвата в регулярном выражении

Идентификатор проверки Gixy: invalid_regex

При использовании регулярных выражений с группами захвата в директивах NGINX, таких как rewrite или в условиях if, вы можете ссылаться на захваченные группы с помощью $1, $2 и т.д. в строках замены или последующих директивах. Однако если вы ссылаетесь на группу захвата, которая не существует в шаблоне regex, NGINX обработает её как пустую строку, что может привести к неожиданному поведению.

Как это найти?

Следует проверить: - Директивы rewrite, где строка замены ссылается на группы захвата (например, $1, $2), которые не существуют в шаблоне regex - Директивы set внутри блоков if, которые ссылаются на группы захвата из шаблона regex условия if - Не захватывающие группы, такие как (?:...), или встроенные модификаторы, такие как (?i), которые не создают нумерованные группы захвата

Примеры

Пример 1: Не захватывающий встроенный модификатор

Проблемная конфигурация:

server {
    location / {
        # (?i) — это флаг регистронезависимости, НЕ группа захвата
        rewrite "(?i)/" $1 break;
    }
}

Проблема: Шаблон (?i)/ использует (?i) для включения регистронезависимого сопоставления, но он не создаёт группу захвата. Ссылка $1 будет пустой.

Исправление:

server {
    location / {
        # Добавьте скобки для создания группы захвата
        rewrite "(?i)/(.*)" /$1 break;
    }
}

Пример 2: Отсутствующие группы захвата

Проблемная конфигурация:

server {
    location / {
        rewrite "^/path" $1 redirect;
    }
}

Проблема: Шаблон ^/path не содержит групп захвата, поэтому $1 будет пустым.

Исправление:

server {
    location / {
        # Либо удалите ненужную ссылку $1
        rewrite "^/path" /newpath redirect;
        # Либо добавьте группу захвата, если необходимо
        rewrite "^/path/(.*)$" /newpath/$1 redirect;
    }
}

Пример 3: Ссылка на неправильный номер группы

Проблемная конфигурация:

server {
    location / {
        # Шаблон имеет только 1 группу захвата, но ссылается на $2
        rewrite "^/(.*)$" /$1/$2 break;
    }
}

Проблема: Шаблон содержит только одну группу захвата (.*), но замена ссылается и на $1, и на $2. Значение $2 будет пустым.

Исправление:

server {
    location / {
        # Добавьте вторую группу захвата, если необходимо
        rewrite "^/([^/]+)/(.*)$" /$2/$1 break;
        # Или удалите некорректную ссылку
        rewrite "^/(.*)$" /prefix/$1 break;
    }
}

Пример 4: Set в блоке if

Проблемная конфигурация:

server {
    location / {
        if ($uri ~ "^/path") {
            set $x $1;  # $1 не существует
        }
    }
}

Проблема: Шаблон regex в условии if не содержит групп захвата, поэтому $1 не определена.

Исправление:

server {
    location / {
        if ($uri ~ "^/path/(.*)$") {
            set $x $1;  # Теперь $1 содержит захваченное значение
        }
    }
}

Что можно сделать?

  1. Добавьте группы захвата в ваш шаблон regex, если вам нужно ссылаться на части совпавшей строки
  2. Удалите ненужные ссылки на группы захвата, если они вам не требуются
  3. Используйте правильные номера групп — помните, что нумерация групп начинается с 1, и $0 недоступен в NGINX
  4. Помните, что не захватывающие группы не создают ссылок — шаблоны типа (?:...), (?i), (?=...) не создают нумерованные группы
  5. Тестируйте ваши шаблоны regex, чтобы убедиться, что они захватывают то, что вы ожидаете

Укрепляйте NGINX с поддерживаемыми RPM

Используйте NGINX Extras от GetPageSpeed для постоянно обновляемого NGINX и модулей на RHEL/CentOS/Alma/Rocky. Подробнее.