Apache. Документация на русском


Разделы:   1    2    3      4      5    6    7    8    9    10    11    12    13    14    15    16  

Раздел 4. Руководство по перезаписи URL

Пункты:   35      36      37    38    39    40    41    42    43    44  

 <         > 
  RU            EN  

Пункт 36. Использование mod_rewrite для перенаправления и переназначения URL-адресов

Этот документ дополняет mod_rewrite справочную документацию. В нем описывается, как вы можете использовать mod_rewrite для перенаправления и переназначения запроса. Это включает в себя множество примеров общего использования mod_rewrite, включая подробное описание того, как каждый из них работает.

Обратите внимание, что многие из этих примеров не будут работать без изменений в вашей конкретной конфигурации сервера, поэтому важно, чтобы вы их поняли, а не просто вырезали и вставляли примеры в свою конфигурацию.

От старого к новому (внутренний)

Описание:

Предположим, мы недавно переименовали страницу foo.html в bar.html и теперь хотим предоставить старый URL-адрес для обратной совместимости. Однако мы хотим, чтобы пользователи старого URL даже не узнавали, что страницы были переименованы — то есть мы не хотим, чтобы адрес менялся в их браузере.

Решение:

Мы переписываем старый URL-адрес на новый внутри с помощью следующего правила:

 RewriteEngine включен
RewriteRule "^ /foo \.html$" " /bar .html" [PT] 

Переписывание со старого на новое (внешнее)

Описание:

Предположим снова, что мы недавно переименовали страницу foo.html в bar.html и теперь хотим предоставить старый URL-адрес для обратной совместимости. Но на этот раз мы хотим, чтобы пользователи старого URL-адреса получали подсказку о новом, т.е. поле Location в их браузерах также должно измениться.

Решение:

Мы принудительно перенаправляем HTTP на новый URL-адрес, что приводит к смене браузеров и, следовательно, к просмотру пользователями:

 RewriteEngine включен
RewriteRule "^ /foo \.html$" " bar .html" [ R ] 
Обсуждение

В этом примере, в отличие от внутреннего примера выше, мы можем просто использовать директиву Redirect. mod_rewrite использовался в предыдущем примере, чтобы скрыть перенаправление от клиента:

 Перенаправление "/foo.html" "/bar.html" 

Ресурс перемещен на другой сервер

Описание:

Если ресурс переместился на другой сервер, вы можете захотеть, чтобы URL-адреса некоторое время продолжали работать на старом сервере, пока люди обновляют свои закладки.

Решение:

Вы можете использовать mod_rewrite для перенаправления этих URL-адресов на новый сервер, но вы также можете рассмотреть возможность использования директивы Redirect или RedirectMatch.

 #С mod_rewrite
RewriteEngine включен
RewriteRule "^/docs/(.+)" "http://new.example.com/docs/$1" [R,L] 
 #С перенаправлением
RedirectMatch "^/docs/(.*)" "http://new.example.com/docs/$1" 
 #С перенаправлением
Перенаправить "/docs/" "http://new.example.com/docs/" 

От статики к динамике

Описание:

Как мы можем преобразовать статическую страницу foo.html в динамический вариант foo.cgi бесшовным способом, т.е. без уведомления браузера/пользователя.

Решение:

Мы просто переписываем URL-адрес CGI-скрипта и заставляем обработчик быть cgi-скриптом , чтобы он выполнялся как CGI-программа. Таким образом, внутренний запрос /~quux/foo.html приводит к вызову /~quux/foo.cgi .

 RewriteEngine включен
RewriteBase "/~quux/"
RewriteRule "^foo\.html$" "foo.cgi" [H= cgi-script ] 

Обратная совместимость для изменения расширения файла

Описание:

Как мы можем сделать URL-адреса обратно совместимыми (все еще существующими виртуально) после перехода document.YYYY на document.XXXX , например, после перевода группы .html файлов на .php ?

Решение:

Мы переписываем имя на его базовое имя и проверяем наличие нового расширения. Если он существует, мы берем это имя, в противном случае мы переписываем URL-адрес в исходное состояние.

 # набор правил обратной совместимости для
# перезаписываем document.html в document.php
# когда и только когда существует document.php
<Каталог "/var/www/htdocs">
 RewriteEngine включен
 Переписать базу "/var/www/htdocs"
 RewriteCond "$1.php" -f
 RewriteCond "$1.html" !-f
 Правило перезаписи "^(.*).html$" "$1.php"
</Каталог> 
Обсуждение

В этом примере используется часто упускаемая возможность mod_rewrite, использующая порядок выполнения набора правил. В частности, mod_rewrite оценивает левую часть RewriteRule до того, как оценивает директивы RewriteCond. Следовательно, $1 уже определен к моменту оценки директив RewriteCond. Это позволяет нам проверить существование исходного ( document.html ) и целевого ( document.php ) файлов, используя одно и то же базовое имя файла.

Этот набор правил предназначен для использования в контексте каждого каталога (в блоке <Directory> или в файле .htaccess), чтобы при проверке -f учитывался правильный путь к каталогу. Возможно, вам потребуется установить RewriteBase директиву, чтобы указать базу каталогов, в которой вы работаете.

Канонические имена хостов

Описание:
Целью этого правила является принудительное использование определенного имени хоста вместо других имен хостов, которые могут использоваться для доступа к тому же сайту. Например, если вы хотите принудительно использовать www.example.com вместо example.com , вы можете использовать вариант следующего рецепта.
Решение:

Самый лучший способ решить эту проблему вообще не включает mod_rewrite, а скорее использует директиву, Redirect помещенную в виртуальный хост для неканонических имен хостов.

 <Виртуальный хост *:80>
 Нежелательное имя сервера.example.com
 Псевдоним сервера example.com notthis.example.com
 Перенаправление "/" "http://www.example.com/"
</ виртуальный хост>
<Виртуальный хост *:80>
 Имя сервера www.example.com
</ виртуальный хост> 

В качестве альтернативы вы можете выполнить это с помощью <If> директивы:

 <Если "%{HTTP_HOST} != 'www.example.com'">
 Перенаправление "/" "http://www.example.com/"
</Если> 

Или, например, чтобы перенаправить часть вашего сайта на HTTPS, вы можете сделать следующее:

 <Если "%{SERVER_PROTOCOL} != 'HTTPS'">
 Перенаправить "/admin/" "https://www.example.com/admin/"
</Если> 

Если по какой-либо причине вы все еще хотите использовать mod_rewrite — если, например, вам нужно, чтобы это работало с большим набором RewriteRules — вы можете использовать один из рецептов ниже.

Для сайтов, работающих на порту, отличном от 80:

 RewriteCond "%{HTTP_HOST}" "!^www\.example\.com" [NC]
RewriteCond "%{HTTP_HOST}" "!^$"
RewriteCond "%{SERVER_PORT}" "!^80$"
RewriteRule "^/?(.*)" "http://www.example.com:%{SERVER_PORT}/$1" [L,R,NE] 

И для сайта, работающего на порту 80

 RewriteCond "%{HTTP_HOST}" "!^www\.example\.com" [NC]
RewriteCond "%{HTTP_HOST}" "!^$"
RewriteRule "^/?(.*)" "http://www.example.com/$1" [L,R,NE] 

Если вы хотите сделать это в общем для всех доменных имен, то есть если вы хотите перенаправить example.com на www.example.com для всех возможных значений example.com , вы можете использовать следующий рецепт:

 RewriteCond "%{HTTP_HOST}" "!^www\." [НЗ]
RewriteCond "%{HTTP_HOST}" "!^$"
RewriteRule "^/?(.*)" "http://www.%{HTTP_HOST}/$1" [L,R,NE] 

Эти наборы правил будут работать либо в вашем основном файле конфигурации сервера, либо в .htaccess файле, размещенном в файле DocumentRoot server.

Поиск страниц более чем в одном каталоге

Описание:

Конкретный ресурс может существовать в одном из нескольких мест, и мы хотим искать в этих местах ресурс, когда он запрашивается. Возможно, недавно мы изменили структуру каталогов, разделив содержимое на несколько мест.

Решение:

Следующий набор правил выполняет поиск в двух каталогах, чтобы найти ресурс, и, если не находит его ни в одном из них, будет пытаться просто обслужить его из запрошенного местоположения.

 RewriteEngine включен
# сначала попытайтесь найти его в каталоге dir1/...
# ...и если нашли, остановитесь и радуйтесь:
RewriteCond "%{DOCUMENT_ROOT}/ dir1 /%{REQUEST_URI}" -f
RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/ dir1 /$1" [L]
# вторая попытка найти его в dir2/...
# ...и если нашли, остановитесь и радуйтесь:
RewriteCond "%{DOCUMENT_ROOT}/ dir2 /%{REQUEST_URI}" -f
RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/ dir2 /$1" [L]
# иначе переходите к другим директивам Alias или ScriptAlias,
# и т. д.
Правило перезаписи "^" "-" [PT] 

Перенаправление на географически распределенные серверы

Описание:

У нас есть множество зеркал нашего веб-сайта, и мы хотим перенаправлять людей на то, которое находится в той стране, где они находятся.

Решение:

Глядя на имя хоста запрашивающего клиента, мы определяем, из какой страны он пришел. Если мы не можем выполнить поиск по их IP-адресу, мы возвращаемся к серверу по умолчанию.

Мы будем использовать RewriteMap директиву для создания списка серверов, которые мы хотим использовать.

 Имя хоста
RewriteEngine включен
Мультиплекс RewriteMap "txt:/path/to/map.mirrors"
RewriteCond "%{REMOTE_HOST}" "([az]+)$" [NC]
RewriteRule "^/(.*)$" "${multiplex: %1 |http://www.example.com/}$1" [R,L] 

## map.mirrors -- Multiplexing Map

de http://www.example.de/
uk http://www.example.uk/
com http://www.example.com/
##EOF##

Обсуждение
Этот набор правил основан на HostNameLookups set on , что может сильно сказаться на производительности.

Директива RewriteCond фиксирует последнюю часть имени хоста запрашивающего клиента — код страны — и следующее правило RewriteRule использует это значение для поиска соответствующего зеркального хоста в файле сопоставления.

Контент, зависящий от браузера

Описание:

Мы хотим предоставлять различный контент в зависимости от браузера или пользовательского агента, который запрашивает контент.

Решение:

Мы должны решить, основываясь на HTTP-заголовке «User-Agent», какой контент обслуживать. Следующая конфигурация делает следующее: Если HTTP-заголовок «User-Agent» содержит «Mozilla/3», страница foo.html перезаписывается foo.NS.html и перезапись останавливается. Если используется браузер «Lynx» или «Mozilla» версии 1 или 2, URL-адрес становится foo.20.html . Все остальные браузеры получают страницу foo.32.html . Это делается с помощью следующего набора правил:

 RewriteCond "%{HTTP_USER_AGENT}" "^ Mozilla/3 .*"
RewriteRule "^foo\.html$" "foo.NS .html " [ L ]
RewriteCond "%{HTTP_USER_AGENT}" "^Lynx/" [ИЛИ]
RewriteCond "%{HTTP_USER_AGENT}" "^Mozilla/[12]"
RewriteRule "^foo\.html$" "foo. 20 .html" [ L ]
RewriteRule "^foo\.html$" "foo.32 .html " [ L ] 

Канонические URL-адреса

Описание:

На некоторых веб-серверах существует более одного URL-адреса для ресурса. Обычно есть канонические URL-адреса (которые фактически используются и распространяются) и те, которые являются просто ярлыками, внутренними и так далее. Независимо от того, какой URL-адрес указал пользователь вместе с запросом, в конечном итоге он должен увидеть канонический URL-адрес в адресной строке своего браузера.

Решение:

Мы делаем внешнее перенаправление HTTP для всех неканонических URL-адресов, чтобы исправить их в представлении местоположения в браузере и для всех последующих запросов. В приведенном ниже примере набора правил мы заменяем /puppies и /canines на канонический /dogs .

 RewriteRule "^/(щенки|собаки)/(.*)" "/dogs/$2" [R] 
Обсуждение:
На самом деле это должно быть выполнено с помощью директив Redirect или RedirectMatch:
 RedirectMatch "^/(щенки|собаки)/(.*)" "/dogs/$2" 

Взолнованный DocumentRoot

Описание:

Обычно адрес DocumentRoot веб-сервера напрямую связан с URL-адресом " / ". Но часто эти данные не имеют приоритета высшего уровня. Например, вы можете пожелать, чтобы посетители при первом входе на сайт переходили в определенный подкаталог /about/ . Этого можно добиться с помощью следующего набора правил:

Решение:

Мы перенаправляем URL-адрес / на /about/ :

 RewriteEngine включен
RewriteRule "^/$" "/about/" [ R ] 

Обратите внимание, что это также может быть обработано с помощью RedirectMatch директивы:

 RedirectMatch "^/$" "http://example.com/about/" 

Также обратите внимание, что в примере перезаписывается только корневой URL-адрес. То есть переписывает запрос на http://example.com/ , но не запрос на http://example.com/page.html . Если вы действительно изменили корень своего документа, то есть если весь ваш контент фактически находится в этом подкаталоге, гораздо предпочтительнее просто изменить вашу DocumentRoot директиву или переместить весь контент вверх в один каталог, а не переписывать URL-адреса.

Резервный ресурс

Описание:
Вы хотите, чтобы один ресурс (скажем, определенный файл, такой как index.php) обрабатывал все запросы, поступающие в конкретный каталог, за исключением тех, которые должны направляться к существующему ресурсу, такому как изображение или файл css.
Решение:

FallbackResource Начиная с версии 2.2.16 для этого следует использовать директиву:

 <Каталог "/var/www/мой_блог">
 Резервный ресурс "index.php"
</Каталог> 

Однако в более ранних версиях Apache или если ваши потребности более сложны, вы можете использовать вариант следующего набора перезаписи для достижения той же цели:

 <Каталог "/var/www/мой_блог">
 RewriteBase "/мой_блог"
 RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-f
 RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-d
 RewriteRule "^" "index.php" [PT]
</Каталог> 

Если, с другой стороны, вы хотите передать запрошенный URI в качестве аргумента строки запроса в index.php, вы можете заменить это RewriteRule на:

 RewriteRule "(.*)" "index.php?$1" [PT,QSA] 

Обратите внимание, что эти наборы правил можно использовать как в .htaccess файле, так и в блоке <Directory>.

Переписать строку запроса

Описание:
Вы хотите получить конкретное значение из строки запроса и либо заменить его, либо включить в другой компонент URL-адреса.
Решения:

Во многих решениях в этом разделе будет использоваться одно и то же условие, при котором совпадающее значение остается в обратной ссылке %2. %1 — это начало строки запроса (до интересующего ключа), а %3 — остаток. Это условие немного сложно для гибкости и для того, чтобы избежать двойных '&&' в заменах.

  • Это решение удаляет соответствующий ключ и значение:
     # Удалить mykey=???
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    Правило перезаписи "(.*)" "$1?%1%3" 
  • Это решение использует захваченное значение в подстановке URL, отбрасывая остальную часть исходного запроса, добавляя '?':
     # Скопировать из строки запроса в PATH_INFO
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteRule "(.*)" "$1/products/%2/?" [ПТ] 
  • Это решение проверяет захваченное значение в последующем условии:
     # Зафиксировать значение mykey в строке запроса
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteCond "%2" !=не очень секретное значение
    Правило перезаписи "(.*)" - [F] 
  • Это решение показывает обратную сторону предыдущих, копируя компоненты пути (возможно, PATH_INFO) из URL-адреса в строку запроса.
     # Нужный URL-адрес может быть /products/kitchen-sink, и скрипт ожидает
    # /path?products=kitchen-sink.
    RewriteRule "^/?path/([^/]+)/([^/]+)" "/path?$1=$2" [PT] 


 <         > 

Пункты:   35      36      37    38    39    40    41    42    43    44  

Рейтинг@Mail.ru