Loading...
X

Обработка строки параметров URI в mod_rewrite

Запросы: request и query

Чтобы не возникло путаницы, начнём с терминов. В английском языке используются два слова request и query. Проблема в том, что они переводятся одинаково как «запрос». При этом они могут использоваться в одном контексте — в английском языке это не вызывает путаницы, а в русском получается «запрос» и «запрос», которые означают разные вещи.

Слово request относится к HTTP запросу. Протокол HTTP передаёт запрос на сервер, в этом запросе содержаться заголовки (например, информация об интересующем хосте (сайте), User-Agent пользователя, имеющиеся для этого сайта кукиз и прочее). Также говорят об URI запроса, методе запроса и так далее. Среди передаваемой информации также имеется query — строка запроса.

К примеру, если я в веб-браузере открою страницу suay.ru/wp-admin/post.php?post=1673&action=edit, то в ней строкой запроса (query) будет post=1673&action=edit, то есть всё то, что следует после ? (знака вопроса).

Как в mod_rewrite искать по параметрам после знака вопроса

Нужно понимать эту разницу, так как по умолчанию mod_rewrite работает с REQUEST_URI, то есть частью запроса, которая НЕ включает в себя строку query. Причём RewriteRule просто игнорирует query.

Очень часто mod_rewrite используется для ЧПУ («красивых» адресов), когда нужно сделать преобразования вида: из

  • site.com/phones/infos/4/52

в

  • site.com/index.php?category=phones&subcat=infos&idc=4&marea=52

В этом случае, как мы видим, исходная строка не содержит строки запроса (query), поэтому при написании правила проблема игнорирования query не возникает:

RewriteEngine on
RewriteRule ([A-Za-z]+)/([A-Za-z]+)/([0-9]+)/([0-9]+) index.php?category=$1&subcat=$2&idc=$3&marea=$4

А что если нам нужно сделать преобразование другого рода:

Из:

http://site.com/category/infos/pages.php?idc=4&marea=52

В:

http://site.com/category/infos/pages.php?marea=52

То есть мы убираем из строки запроса (query) параметр idc вместе с его значением.

В этом случае мы уже не можем использовать RewriteRule, поскольку его правила полностью игнорируют строку query. Правда, используя некоторые флаги можно сделать так, чтобы исходная строка запроса query добавлялась к новому URI — но нам в рассматриваемой ситуации нужно не это.

Проблема решается с использованием директивы RewriteCond, которая умеет работать с переменной QUERY_STRING, содержащей строку query с запросом.

Что нам нужно знать про RewriteCond? Директива RewriteCond оказывает воздействие на RewriteRule, которое следует после строки (или блока строк) RewriteCond. В RewriteCond также можно использовать обратные ссылки, но для разграничения от обратных ссылок RewriteRule, вместо $ (знака доллара) используется % (знак процента), то есть вместо $1, первая обратная ссылка обозначается как %1.

Итак, составляем RewriteCond для нашего случая:

RewriteCond "%{QUERY_STRING}" "idc=([0-9]+)&marea=([0-9]+)$"

Рассмотрим эту строку подробно.

%{QUERY_STRING} означает, что анализируется строка запроса, следующая в URI после знака вопроса.

Строка idc=([0-9]+)&marea=([0-9]+)$ представляет собой шаблон поиска. То есть ищется строка, которая начинается на idc=, затем следуют цифры (одна или более) — причём, поскольку это регулярное выражение в скобках, то найденные цифры помещаются в первую обратную ссылку, затем идёт строка &marea=, затем опять цифры (одна или более), причём найденные цифры помещаются во вторую обратную ссылку. В данном случае символ $ означает конец анализируемой строки.


Чего мы этим добились? Мы сделали так, что значение idc будет помещено в первую обратную ссылку, а значение marea будет помещено во вторую обратную ссылку.

Переходим непосредственно к правилу перезаписи RewriteRule:

RewriteRule "(.*)" "/$1?marea=%2" [L,R]

Рассмотрим это содержимое подробно:

Регулярное выражение (.*) означает «что угодно». Но мы помним, что это «что угодно» игнорирует строку запроса query. То есть это URI без строки query. Причём, поскольку это регулярное выражение в скобках, то оно помещается в первую обратную ссылку.

Далее строка /$1?marea=%2. Она начинается с указания на корневую папку сайта (/), затем идёт первая обратной ссылка $1, в неё помещается весь URI кроме строки запроса, затем добавляется строка ?marea=, к которой добавляется то, что содержится во второй обратной ссылке (%2) от RewriteCond.

Флаги [L,R] означают завершить проверку по другим правилам и сделать редирект на новый адрес (то есть адрес страницы измениться в адресной строке веб-браузера пользователя).

В результате получится, что адрес:

  • http://site.com/category/infos/pages.php?idc=4&marea=52

Превратится в:

  • http://site.com/category/infos/pages.php?marea=52

Соберём условие перезаписи и правило перезаписи вместе:

RewriteEngine on
RewriteCond "%{QUERY_STRING}" "idc=([0-9]+)&marea=([0-9]+)$"
RewriteRule "(.*)" "/$1?marea=%2" [L,R]

Как с mod_rewrite удалить параметр из URI

Эта конструкция приводит к тому, что будет «вырезано» значение определённого параметра из получаемой строки запроса. Если говорить более точно, строка запроса будет заново пересобрана, но уже без одного из своих параметров. Используя эту технику можно убирать один или несколько параметров из запроса, либо присваивать их значения другим параметрам.

RewriteEngine    On
RewriteCond      %{QUERY_STRING}    ^page=1$
RewriteRule      (.*)               $1?     [R=permanent]

Построчно:

  1. Вы включаете функцию перезаписи.
  2. В качестве условия («оператор если») вы указываете, что строка запроса должна быть точно page=1, чтобы применялись следующие правила.
  3. Затем вы указываете правило, которое говорит, что нужно заменить весь путь (.*) на него же ($1), но сделать строку запроса пустой (?) и на этот результат выполняется постоянный редирект permanent redirect (301).

Если вы хотите, чтобы перенаправление было временным (302), вы можете просто удалить часть =permanent. Moved Temporarily (временно перемещено) это значение по умолчанию для флага R.

Перемещено Временно - значение по умолчанию для флага R.

mod_rewrite: отрицание в строке запроса %{QUERY_STRING}

Рассмотрим отрицание в строках запроса, то есть когда правило RewriteRule применяется только к запросам, в которых у query отсутствует определённая строка. Для этого перед Шаблоном укажите ! (восклицательный знак) или конструкцию !=. Также Шаблон не нужно помещать в кавычки, иначе условие перестаёт работать. В результате RewriteRule будет применено только к запросам без указанной строки в query (в данном случае без fromsubdomain=true).

RewriteEngine On
RewriteCond "%{QUERY_STRING}" !=fromsubdomain=true [NC]
RewriteRule subdomain/([^/]+) https://$1.suay.ru

Ничего не поняли? Значит начните изучение mod_rewrite с самых основ. Подробный учебник по mod_rewrite на русском языке здесь.

Рекомендуется вам:


Leave Your Observation

Ваш адрес email не будет опубликован. Обязательные поля помечены *

wp-puzzle.com logo

Бесплатная карта с кэшбэком 1,5% и до 5% на остаток (Альфа-Карта) + бонус 500 рублей за первую покупку

Кредитная карта только по паспорту! Бесплатное снятие наличных

Scroll Up