RewriteRule и query_string

версия для печати

Понадобилось мне после слияния сайтов описать правило для mod_rewrite типа

http://sub.site.ru/?id=NN -> http://site.ru/NN

Согласен, обычно наоборот пишут, но надо мне так.. Делаю все по мануалу Apache и ничего не получаю. Порылся в инете и нашел решение, которое работало, хотя в разрез с документацией. Еще полчаса в поисках объяснения этого явления привели меня к статье на английском как раз о том, как mod_rewrite реально работает с query_string. Собственно вольный перевод прилагается.

Оригинал здесь. Статья написана в январе 2009, но актуальна до сих пор.

На первый взгляд, способ, которым mod_rewrite работает со строками GET-запроса, слегка озадачивает. Из оффициальной документации по RewriteRule:

флаг qsappend|QSA (query string append - дописать строку запроса)

Этот флаг указывает движку rewrite-a дописать параметры GET-запроса к существующей строке, вместо того, чтобы заменить их. Используйте этот флаг, когда хотите добавить свои парамеры в строку запроса через RewriteRule.

Давайте попробуем сделать редирект на страницу, в зависимости от строки запроса. Для примера возьмем адрес типа http://mydomain.site/page.php?id=NN, где NN - число. Правило rewrite-а должно бы выглядеть так:

RewriteCond %{QUERY_STRING} ^id=([0-9]*)$
RewriteRule ^page\.php$ http://mydomain.site/page/%1.php [R=302,L]
Согласно оффициальной документации, нам следует ожидать следующее поведение: /page.php?id=37 -> http://mydomain.site/page/37.php
/page.php?id=40 -> http://mydomain.site/page/40.php
# и так далее

Как бы там ни было, если вы не допишете что-то новое, то исходная строка запроса (GET-параметры) пройдет через правила без изменений:

/page.php?id=37 -> http://mydomain.site/page/37.php?id=37
/page.php?id=40 -> http://mydomain.site/page/40.php?id=40
# и так далее

Если вы хотите убрать исходную строку запроса, нужно в конце подстановки писать знак вопроса. Давайте назовем его "флагом отмены строки запроса":

RewriteCond %{QUERY_STRING} ^id=([0-9]*)$
RewriteRule ^page\.php$ http://mydomain.site/page/%1.php? [R=302,L]
Вот с этим "флагом" новый URL будет выглядеть, как ожидается.

Краткая справка по работе со строкой запроса в RewriteRule:

Сохранить исходный запрос (поведение по умолчанию)
RewriteRule ^page\.php$ /target.php [L]
# из http://example.com/page.php?foo=bar
# в http://example.com/target.php?foo=bar

Удалить исходный запрос
RewriteRule ^page\.php$ /target.php? [L]
# из http://example.com/page.php?foo=bar
# в http://example.com/target.php

Заменить исходный запрос
RewriteRule ^page\.php$ /target.php?bar=baz [L]
# из http://example.com/page.php?foo=bar
# в http://example.com/target.php?bar=baz

Дописать новый запрос к исходному
RewriteRule ^page\.php$ /target.php?bar=baz [QSA,L]
# из http://example.com/page.php?foo=bar
# в http://example.com/target.php?foo=bar&bar=baz

И кое-что от меня лично (переводчик). Текущий GET-запрос к поддомену превратить в ЧПУ родительского домена:

RewriteCond %{HTTP_HOST} sub\.example\.com [NC]
RewriteCond %{QUERY_STRING} ^id=(.+)$
RewriteRule ^.*$ http://example.com/%1? [R=301,L]
# из http://sub.example.com/id=12
n# в http://example.com/12

Здесь %1 - это ссылка на часть условия, не путать с $1 - ссылка в шаблон.

[1oo%, EoF]

Понравилась статья? Расскажите о ней друзьям:


Комментарии
Для работы модуля комментариев включите javaScript


Показать/скрыть правила
Имя
[i] [b] [u] [s] [url]
:-) ;-) :D *lol* 8-) :-* :-| :-( *cry* :o :-? *unsure* *oops* :-x *shocked* *zzz* :P *evil*

Осталось 1000 символов.
Код защиты от спама Обновить код
Каждый комментарий проходит ручную модерацию. 100% фильтрация спама.
Продвижение
Время
Метки