Модуль http_rewrite#

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

Директивы break, if, return, rewrite и set обрабатываются в следующем порядке:

  • последовательно выполняются директивы этого модуля, описанные на уровне server;

  • в цикле:

    • ищется location по URI запроса;

    • последовательно выполняются директивы этого модуля, описанные в найденном location;

    • цикл повторяется, если URI запроса изменялся, но не более 10 раз.

Директивы#

break#

Синтаксис:

break;

Умолчание:

Контекст:

server, location, if

Завершает обработку текущего набора директив модуля http_rewrite.

Если директива указана внутри location, дальнейшая обработка запроса продолжается в этом location.

Пример:

if ($slow) {
    limit_rate 10k;
    break;
}

if#

Синтаксис:

if (условие) { … }

Умолчание:

Контекст:

server, location

Проверяется указанное условие. Если оно истинно, то выполняются указанные в фигурных скобках директивы этого модуля и запросу назначается конфигурация, указанная внутри директивы if. Конфигурации внутри директив if наследуются с предыдущего уровня конфигурации.

В качестве условия могут быть заданы:

  • имя переменной; ложными значениями переменной являются пустая строка или «0»;

  • сравнение переменной со строкой с помощью операторов «=» и «!=»;

  • соответствие переменной регулярному выражению с учетом регистра символов — «~» и без него — «~*». В регулярных выражениях можно использовать выделения, которые затем доступны в виде переменных $1..$9. Также можно использовать отрицательные операторы «!~» и «!~*». Если в регулярном выражении встречаются символы «}» или «;», то все выражение следует заключить в одинарные или двойные кавычки.

  • проверка существования файла с помощью операторов «-f» и «!-f»;

  • проверка существования каталога с помощью операторов «-d» и «!-d»;

  • проверка существования файла, каталога или символической ссылки с помощью операторов «-e» и «!-e»;

  • проверка исполняемости файла с помощью операторов «-x» и «!-x».

Примеры:

if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
}

if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
}

if ($request_method = POST) {
    return 405;
}

if ($slow) {
    limit_rate 10k;
}

if ($invalid_referer) {
    return 403;
}

Примечание

Значение встроенной переменной $invalid_referer задается директивой valid_referers.

return#

Синтаксис:

return код [текст];
return код URL;
return URL;

Умолчание:

Контекст:

server, location, if

Завершает обработку и возвращает клиенту указанный $1. Нестандартный код 444 закрывает соединение без передачи заголовка ответа.

Можно задать либо URL перенаправления (для кодов 301, 302, 303, 307 и 308) либо текст тела ответа (для остальных кодов). В тексте тела ответа и URL перенаправления можно использовать переменные. Как частный случай, URL перенаправления может быть задан как URI, локальный для данного сервера, при этом полный URL перенаправления формируется согласно схеме запроса ($scheme) и директивам server_name_in_redirect и port_in_redirect.

Кроме того, в качестве единственного параметра можно указать URL для временного перенаправления с кодом 302. Такой параметр должен начинаться со строк «http://», «https://» или «$scheme». В URL можно использовать переменные.

См. также директиву error_page.

rewrite#

Синтаксис:

rewrite regex замена [флаг];

Умолчание:

Контекст:

server, location, if

Если указанное регулярное выражение соответствует URI запроса, URI изменяется в соответствии со строкой $1. Директивы rewrite выполняются последовательно, в порядке их следования в конфигурационном файле. С помощью $1 можно прекратить дальнейшую обработку директив. Если строка $1 начинается с «http://», «https://» или «$scheme», то обработка завершается и клиенту возвращается перенаправление.

Необязательный параметр $1 может быть одним из:

last

завершает обработку текущего набора директив модуля http_rewrite, после чего ищется новый location, соответствующий измененному URI;

break

завершает обработку текущего набора директив модуля http_rewrite аналогично директиве break;

redirect

возвращает временное перенаправление с кодом 302; используется, если строка $1 не начинается с «http://», «https://» или «$scheme»;

permanent

возвращает постоянное перенаправление с кодом 301.

Полный URL перенаправлений формируется согласно схеме запроса ($scheme) и директив server_name_in_redirect и port_in_redirect.

Пример:

server {
#    ...
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  last;
    return  403;
#    ...
}

Если же эти директивы поместить в location «/download/», то нужно заменить флаг last на break, иначе Angie сделает 10 циклов и вернет ошибку 500:

location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  break;
    return  403;
}

Если в строке $1 указаны новые аргументы запроса, то предыдущие аргументы запроса добавляются после них. Если такое поведение нежелательно, можно отказаться от этого добавления, указав в конце строки замены знак вопроса, например:

rewrite ^/users/(.*)$ /show?user=$1? last;

Если в регулярном выражении встречаются символы «}» или «;», то все выражение следует заключить в одинарные или двойные кавычки.

rewrite_log#

Синтаксис:

rewrite_log on | off;

Умолчание:

rewrite_log off;

Контекст:

http, server, location, if

Разрешает или запрещает записывать в error_log на уровне notice результаты обработки директив модуля http_rewrite.

set#

Синтаксис:

set $переменная значение;

Умолчание:

Контекст:

server, location, if

Устанавливает значение указанной переменной. В качестве значения можно использовать текст, переменные и их комбинации.

uninitialized_variable_warn#

Синтаксис:

uninitialized_variable_warn on | off;

Умолчание:

rewrite_log on;

Контекст:

http, server, location, if

Определяет, нужно ли писать в лог предупреждения о неинициализированных переменных.

Внутреннее устройство#

Директивы модуля http_rewrite компилируются на стадии конфигурации во внутренние инструкции, интерпретируемые во время обработки запроса. Интерпретатор представляет из себя простую стековую виртуальную машину.

Например, директивы

location /download/ {
    if ($forbidden) {
        return 403;
    }

    if ($slow) {
        limit_rate 10k;
    }

    rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break;
}

будут транслированы в такие инструкции:

переменная $forbidden
проверка на ноль
    возврат 403
    завершение всего кода
переменная $slow
проверка на ноль
проверка регулярного выражения
копирование "/"
копирование $1
копирование "/mp3/"
копирование $2
копирование ".mp3"
завершение регулярного выражения
завершение всего кода

Обратите внимание, что инструкций для директивы limit_rate нет, поскольку она не имеет отношения к модулю http_rewrite. Для блока if создается отдельная конфигурация. Если условие истинно, запрос получает эту конфигурацию, и в ней limit_rate равен 10k.

Директиву

rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break;

можно сделать на одну инструкцию меньше, если в регулярном выражении перенести первую косую черту внутрь скобок:

rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;

Тогда соответствующие инструкции будут выглядеть так:

проверка регулярного выражения
копирование $1
копирование "/mp3/"
копирование $2
копирование ".mp3"
завершение регулярного выражения
завершение всего кода