Создание сайтов в Абакане и продвижение

Mod Rewrite и ISAPI_Rewrite для перезаписи и перенаправления URL

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

ModRewrite для сервера Apache и ISAPI Rewrite для сервера Microsoft IIS Server предлагают очень мощные способы переписывания ваших URL. Вот некоторые причины для использования этих мощных инструментов:
♦    вы изменили структуру URL вашего сайта таким образом, что контент переместился из одного места в другое. Такое может произойти при замене системы CMS или при изменении организации вашего сайта (по любой причине);
♦    вы хотите поставить в соответствие вашим недружественным для поисковых движков URL более дружественные URL.
Если вы используете в качестве web-cepeepa Apache, то должны будете разместить директивы "правил перезаписи" в файле .htaccess или в файле конфигурации вашего сервера Apache (например, в файле httpd.conf или в специфичном для сайта файле конфигурации (в каталоге sites_conf)). Если же вы используете IIS Server, то примените дополнительный модуль ISAPI (такой, как ISAPI_Rewrite) и разместите правила в конфигурационном файле httpd.ini.
Обратите внимание, что правила ISAPI Rewrite несколько отличаются от правил modrewrite. Дальнейшее наше обсуждение будет сосредоточено на mod rewrite.
Ваш файл .htaccess должен начинаться со следующего: SewriteEngine on RewriteBase /
Если вы добавляете правила перезаписи в файл конфигурации вашего сервера, то следует опустить вторую строку (поскольку RewriteBase поддерживается только для .htaccess). Мы используем здесь RewriteBase для того, чтобы вы могли писать только л (а не л/) в начале каждого правила (регулярные выражения мы скоро обсудим).
После этого шага правила перезаписи будут готовы. Возможно, вы захотите иметь запросы товарных страниц в виде http://www.yourdomain.com/products/123 «для показа контента по адресу http://www.yourdomain.com/get_product.php?id=123) без изменения URL в поле Location браузера пользователя и без необходимости изменять скрипт get_product.php. Конечно, это не заменит все динамические URL в ссылках на всех страницах сайта (это отдельная проблема). Вы можете реализовать первую часть задачи при помощи одного правила перезаписи, примерно такого:
P.ewriteRule "products/([0-9] +)/?$ /getj>roduct.php?id=$l [L]

Здесь web-серверу указывается на то, что все приходящие на каталог /product/ запросы следует преобразовывать в запросы к /get_product.php, при этом подкаталог каталога /product/ используется как параметр для скрипта РНР. Теперь посмотрим, что есть что:
♦    знак Л обозначает начало URL (после имени домена);
♦    знак $ обозначает конец URL;
♦    [0-9] обозначает цифру;
♦    следующий сразу за цифрой знак + означает одно или несколько вхождений цифры;
♦    аналогично, знак ? сразу же за знаком / обозначает ноль или одно вхождение символа косой черты;
♦    скобки о помещают в память то, что в них находится;
♦    при помощи $1 вы можете обратиться к тому, что сохранено в памяти (к тому, что было в первом комплекте скобок). Естественно, что при использовании в правиле второго комплекта скобок вы сможете получить к ним доступ при помощи $2 (и т. д.);
♦    флаг [L] экономит на обработке сервером, он говорит движку перезаписи о том, что в случае совпадения с правилом нужно остановиться. В противном случае все оставшиеся правила также будут выполнены.

Вот несколько более сложный пример, где URL формата http:// www .yourdomain.coni/webapp/wcs/stores/se rvlet/ProductDisp!ay?storeId=10001&c atalogId=10001&langId=-l&categoryID=4&productID=123 будут перезаписываться как http://www.yourdomain.eom/4/123.htm:
RewriteRule Л([л/]+)/([л/]+)\.htm$
/webapp/wcs/stores/servlet/ProductDisplay?storeId=10001ScatalogId=10001& langId=-lscategoryID=$liproductID=$2 [QSA,L]

Здесь:
♦    знак [л/] обозначает любой символ, кроме косой черты, потому что внутри квадратных скобок знак Л интерпретируется как "нет";
♦    флаг [QSA] предназначен для случая, когда вы не хотите отбрасывать строку запроса (например, когда хотите сохранить параметр отслеживания).
Чтобы писать хорошие правила перезаписи, вам нужно стать специалистом по сопоставлению с шаблонами (это просто другое название работы с регулярными выражениями).
Вот некоторые из самых важных специальных символов и то, как они интерпретируются движком перезаписи:
* означает 0 или более повторений предыдущего символа;
+ означает 1 или более повторений предыдущего символа;
? означает 0 или 1 вхождение предыдущего символа;
Л означает начало строки;
$ означает конец строки;
. означает любой символ (т. е. работает как групповой символ);
\ означает "отказ" от специального значения следующего символа (например, \.| означает то, что точка является не групповым символом, а обычным символом); ;
♦    Л внутри скобок [] означает "нет" (например, [Л/] означает "не косая черта". В регулярных выражениях очень легко наделать ошибок.
Вот некоторые из наиболее часто встречающихся ошибок, которые могут привести к ненамеренным совпадениям строк:
♦    применение .* в том случае, когда нужно использовать .+ (поскольку .* не может совпасть ни с чем);
♦    отсутствие "отказа" от специального символа, который вы не хотите интерпретировать (например, когда вы указываете . вместо \. и имеете в виду символ
j точки, а не любой символ). Таким образом, default.htm совпадет с defaulthtm, а I defaultA.htm совпадет ТОЛЬКО С default.htm;
♦    пропуск А или $ (в предположении, что начало или конец подразумеваются), т. е.
I defaultX.htmсовпадет С mydefault.html, a Adefault\.htm$ совпадет ТОЛЬКО С default.htm;
♦    использование "жадных" выражений, которые совпадут со всеми вхождениями (вместо того, чтобы остановиться после первого вхождения).
\ Самый простой способ проиллюстрировать "жадные" выражения — дать пример:
JRewriteRule л(.*)/?index\.html$ /$1/ [L,R=301]

Здесь производится редирект запросов с http://www.yourdomain.com/blah/ index.html на http://www.yourdomain.com/blah//. Вероятно, это не то, что планировалось сделать. Почему так получилось?
Потому что .* захватит символ косой черты еще до того, как /? его увидит. К счастью, это просто исправить. Нужно использовать [Л или .*? (вместо .*). Например, используйте Л(.*?)/? вместо л(.*)/? или [Л/]+/[Л/] вместо .*/.*.
Итак, чтобы исправить предыдущее правило, вы можете написать следующее: RewriteRule *(.*?)/?index\.html$ /$1/ [L,R=301]
Почему бы не использовать вот такое:
RewriteRule А([А/]*)/?index\.html$ /$1/ [L,R=301]
Это более ограниченный вариант, поскольку он будет давать совпадения только для URL с одним каталогом. URL с несколькими подкаталогами (например, http://www.yourdomain.com/store/cheese/swiss/wheel/index.html) совпадать не будут.
Понятно, что тестирование и отладка— это существенная часть перезаписи URL. Ваши лучшие друзья при отладке — директивы RewriteLog И RewriteLogLevel. Установите RewriteLogLevel в значение 4 и посмотрите, что делает движок перезаписи при интерпретации ваших правил.
Кстати, флаг [R=301] в последних нескольких примерах (как легко догадаться) говорит движку перезаписи о необходимости выполнить 301-й редирект (вместо стандартной перезаписи).
Есть еще одна очень удобная для совместного использования с RewriteRule директива под названием RewriteCond. Директиву RewriteCond следует использовать в тех случаях, когда вы пытаетесь найти совпадение в строке запроса, имени домена или прочих вещах (не присутствующих между именем домена и знаком вопроса в URL).
Обратите внимание, что ни RewriteRule, ни RewriteCond не могут обращаться к тому, что находится в якорной части URL, т. е. к тому, что следует за знаком #, поскольку оно используется браузером внутренним образом и не посылается на сервер как часть запроса.
А вот пример, когда RewriteCond ищет совпадение имени хоста и только после этого разрешает выполнить следующее далее правило перезаписи:
RewriteCond %{HTTP_HOST} !Awww\.yourdomain\.com$ [NC] RewriteRule Л(.*)$ http://www.yourdomain.com/$l [L,R=301]
Обратите внимание на знак восклицания в начале регулярного выражения. Движок перезаписи интерпретирует это как "нет".
Для любого имени хоста (кроме http://www.yourdomain.com) выдается 301-й редирект на эквивалентный канонический URL поддомена www. Флаг [NC] делает условие перезаписи нечувствительным к регистру.
Вы можете спросить, где же флаг [QSA] для сохранения строки запроса? При ре- директе он не нужен, т. к. в этом случае он просто подразумевается.
Если вы не хотите сохранять строку запроса в правиле перезаписи с редиректом. то поставьте в правиле знак вопроса в конец URL назначения:
RewriteCond %(HTTP_HOST} !Awww\.yourdomain\.com$ [NC] RewriteRule Л(.*)$ http://www.yourdomain.com/$l? [L,R=301]
Почему мы не используем Ayourdomain\.com? ?
Рассмотрим:
RewriteCond %{HTTP_HOST) Ayourdomain\.com$ [NC] RewriteRule Л(.*)$ http://www.yourdomain.com/$l? [L,R=301]
Это не даст совпадений для доменов с опечатками вроде yourdoamin.com, на которые будут отвечать сервер DNS и виртуальный хост (если предположить, что ошибочно был написан тот домен, который зарегистрировали вы и который принадлежит вам).
При каких обстоятельствах вам может понадобиться опустить строку запроса из перенаправленного URL (как мы это делали в предыдущих двух примерах)? Когда нужно опустить идентификатор сеанса или параметр отслеживания (такой, как source=banner_adl)? Сохранение параметра отслеживания после редиректа не только не нужно (поскольку оригинальный URL с приписанным к нему исходным кодоад будет записан в ваших журналах доступа), но и нежелательно с точки зрения канонизации. Что будет, если вы захотите отбросить параметр отслеживания из перенаправленного URL, но сохранить остальные параметры строки запроса?
Вот как это можно сделать для статических URL: RewriteCond %{QUERY_STRING) Asource=[a-z0-9]*$ RewriteRule Л(.*)$ 7$1? [L,R=301]
И для динамических URL:
RewriteCond %(QUERY_STRING) Л(.+)&source=[a-zO-9]+(&?.*)$ RewriteRule л(.*)$ /$1?%1%2 [L,R=301]
Хотите до перенаправления пользователя сделать что-то забавное при помощи куки-файлов?
Запустите скрипт, который делает куки-файл для пользователя, и затем перенаправьте его 301-м редиректом на канонический URL:

RewriteCond %(QUERY_STRING} Asource=([a-z0-9]*)$ |BewriteRule A(.*)$ /cookiefirst.php?source=%lSdest=$l [L]
Обратите внимание на отсутствие в предыдущем коде флага [R=30l]. Это сделано специально. Нет необходимости демонстрировать этот скрипт пользователю. Используйте перезапись и пусть скрипт сам отправит 301-й редирект после завершения своей работы.
Прочие случаи корректировок проблем канонизации при помощи правил пере- | записи и флага [R=30l]:
когда поисковые движки индексируют страницы каталогов с указателями HTTPS;
когда в конце URL отсутствует косая черта (которая там должна быть).

Сначала корректировка для HTTPS:
♦ redirect online catalog pages in the /catalog/ directory if HTTPS iewriteCond %(HTTPS} on
:FewriteRule Acatalog/(.*) http://www.yourdomain.com/catalog/$l [L,R=301]
Обратите внимание: если ваш безопасный сервер отделен от вашего основного сервера, то можно опустить строку RewriteCond.
Теперь для добавления концевой косой черты:
RewriteRule А(. *[*/])$ /$1/ [L,R=301]
После того как проект по перезаписи URL (для миграции с динамических на статические URL) будет завершен, вы захотите убрать динамические URL (не простой заменой всех вхождений устаревших URL вашего сайта, а при помощи 301-го редиректа устаревших динамических URL на их новые статические эквиваленты). При таком способе любые (указывающие на удаленные URL) входящие ссылки приведут и пауков, и людей на правильные новые URL, обеспечив их индексирование, ссылки и закладки на них (а старые URL будут удалены из индекса). Вот как можно этого добиться: RewriteCond %{QUERY_STRING} id=([0-9]+) RewriteRule Aget_product\.php$ /products/U.html? [L,R=301]
Однако если вы не будете осторожны, то получите бесконечный цикл рекурсивных редиректов. Быстрый (но некрасивый) способ избежать этого — добавить бессмысленный параметр в URL назначения при перезаписи и обеспечить отсутствие этого бессмысленного параметра перед выполнением редиректа, например: RewriteCond %{QUERY_STRING} id=([0-9]+) RewriteCond %(QUERY_STRING} !blah=blah RewriteRule Aget_product\.php$ /products/11.html? [L,R=301] RewriteRule Aproducts/([0-9]+)/?$ /get_product.php?id=$lsblah=blah [L]
Обратите внимание, что в примере использованы две строки RedirectCond (одна над другой). Все условия редиректа, перечисленные в одном блоке, будут связаны операцией AND. ЕСЛИ ВЫ хотите, чтобы их связывала логическая операция OR, то придется использовать флаг [OR] .

 

Seo Info

You are here: