Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Методы перенаправления и переписывания URL
Редиректы можно делать множеством способов. На web-сервере Apache (обычно это компьютеры под управлением операционных систем UNIX или Linux) можно очень просто реализовать редирект – в стандартном файле под названием. htaccess при помощи директив Redirect и RedirectMatch (подробнее о формате этого файла читайте по адресу http: //httpd.apache.org/docs/2.2/howto/htaccess.html). Можно использовать также и более сложные директивы (известные как".правила перезаписи" ) при помощи модуля сервера Apache под названием mod_rewrite (который мы скоро обсудим). На web-серверах Microsoft IIS (http: //www.iis.net/) для реализации редиректов имеются разные методы. Основной метод выполнения редиректов – при помощи консоли IIS (подробнее об этом можно прочитать по адресу http: //www.mcanerin.com/EN/articles/301-redirect-HS.asp). Можно также использовать текстовый файл с директивами (при условии применения дополнительного модуля ISAPI, такого как ISAPI Rewrite (http: //www.isapirewrite.com/). Этот язык скриптов предлагает такие возможности, которые аналогичны модулю mod rewrite сервера Apache. Многие программисты используют для реализации редиректов и другие способы. Это можно сделать непосредственно в языках программирования (таких, как Perl, PHP, ASP и JavaScript). Если программист реализует редиректы таким путем, то он должен убедиться, что web-сервер возвращает код состояния 301. Вы можете проверить заголовок, который возвращается дополнительным модулем Live HTTP Headers (http: //livehttpheaders.mozdev.org/) браузера Firefox. Еще один способ реализации редиректа – это выполнить его на уровне страницы при помощи метатега refresh, который выглядит примерно так: < meta http-equiv=" refresh" content=" 5; url=http: //www.yourdomain.com/newlocation.htm" /> Первый параметр в разделе контента (число 5) указывает количество секунд, которое web-сервер должен подождать перед перенаправлением пользователя на указанную страницу. Это применяется в тех сценариях, когда издатель хочет показать страницу, позволяющую пользователю понять, что он будет перенаправлен на другую страницу (а не на ту, которую запросил). Проблема состоит в том, что большая часть таких метаобновлений обрабатывается как 302-й редирект. Единственное исключение из этого правила, если вы указываете задержку редиректа в 0 секунд. Вам придется отказаться от показа вашей предупредительной страницы, говорящей пользователю о том, что вы переносите его, но поисковые движки будут обрабатывать это как 301-й редирект (для надежности лучше все же по возможности просто использовать 301-й редирект). Mod_rewrite и ISAPI_Rewrite для перезаписи и перенаправления URL Эта тема гораздо шире тех возможностей, которые мы имеем в рамках данной книги. Нижеследующее описание предназначено служить исключительно введением в данную тему, чтобы помочь технически продвинутым читателям (и в том числе web-разработчикам и web-мастерам) понять функционирование перезаписи и перенаправления. Если вы хотите пропустить это техническое описание, переходите к следующему разделу. Modrewrite для сервера Apache и ISAPIRewrite для сервера Microsoft IIS Server предлагают очень мощные способы переписывания ваших URL. Вот некоторые причины для использования этих мощных инструментов: • вы изменили структуру URL вашего сайта таким образом, что контент переместился из одного места в другое. Такое может произойти при замене системы CMS или при изменении организации вашего сайта (по любой причине); • вы хотите поставить в соответствие вашим недружественным для поисковых движков URL более дружественные URL. Если вы используете в качестве web-сервера Apache, то должны будете разместить директивы " правил перезаписи" в файле. htaccess или в файле конфигурации вашего сервера Apache (например, в файле httpd.conf или в специфичном для сайта файле конфигурации (в каталоге sites_conf)). Если же вы используете IIS Server, то примените дополнительный модуль ISAPI (такой, как ISAPI_Rewrite) и разместите правила в конфигурационном файле httpd.ini. Обратите внимание, что правила ISAPI_Rewrite несколько отличаются от правил mod rewrite. Дальнейшее наше обсуждение будет сосредоточено на mod rewrite. Ваш файл. htaccess должен начинаться со следующего: RewriteEngine on RewriteBase / Если вы добавляете правила перезаписи в файл конфигурации вашего сервера, то следует опустить вторую строку (поскольку RewriteBase поддерживается только для. htaccess). Мы используем здесь RewriteBase для того, чтобы вы могли писать только ^ (а не ^/) в начале каждого правила (регулярные выражения мы скоро обсудим). После этого шага правила перезаписи будут готовы. Возможно, вы захотите иметь запросы товарных страниц в виде http: //www.yourdomain.com/products/123(для показа контента по адресу at http: //www.yourdomain.com/get_product.php? id=123) без изменения URL в поле Location браузера пользователя и без необходимости изменять скрипт get_product.php. Конечно, это не заменит все динамические URL в ссылках на всех страницах сайта (это отдельная проблема). Вы можете реализовать первую часть задачи при помощи одного правила перезаписи, примерно такого: RewriteRule ^products/([0–9]+)/? $ /get_product.php? id=$1 [L] Здесь web-серверу указывается на то, что все приходящие на каталог /product/ запросы следует преобразовывать в запросы к /get_product.php, при этом подкаталог каталога /product/ используется как параметр для скрипта PHP. Теперь посмотрим, что есть что: • знак ^ обозначает начало URL (после имени домена); • знак $ обозначает конец URL; • [0–9] обозначает цифру; • следующий сразу за цифрой знак + означает одно или несколько вхождений цифры; • аналогично, знак? сразу же за знаком / обозначает ноль или одно вхождение символа косой черты; • скобки () помещают в память то, что в них находится; • при помощи $1 вы можете обратиться к тому, что сохранено в памяти (к тому, что было в первом комплекте скобок). Естественно, что при использовании в правиле второго комплекта скобок вы сможете получить к ним доступ при помощи $2 (и т. д.); • флаг [L] экономит на обработке сервером, он говорит движку перезаписи о том, что в случае совпадения с правилом нужно остановиться. В противном случае все оставшиеся правила также будут выполнены. Вот несколько более сложный пример, где URL формата http: //www.yourdomain.com/webapp/wcs/stores/servlet/ProductDisplay? storeId=10001& catalogId=10001& langId=-1& categoryID=4& productID=123 будут перезаписываться как http: //www.yourdomain.com/4/123.htm: RewriteRule ^([^/]+)/([^/]+)\.htm$ /webapp/wcs/stores/servlet/ProductDisplay? storeId=10001& catalogId=10001& langId=-1& categoryID=$1& productID=$2 [QSA, L] Здесь: • знак [/] обозначает любой символ, кроме косой черты, потому что внутри квадратных скобок знак ^ интерпретируется как " нет"; • флаг [QSA] предназначен для случая, когда вы не хотите отбрасывать строку запроса (например, когда хотите сохранить параметр отслеживания). Чтобы писать хорошие правила перезаписи, вам нужно стать специалистом по сопоставлению с шаблонами (это просто другое название работы с регулярными выражениями). Вот некоторые из самых важных специальных символов и то, как они интерпретируются движком перезаписи: • * означает 0 или более повторений предыдущего символа; • + означает 1 или более повторений предыдущего символа; •? означает 0 или 1 вхождение предыдущего символа; • ^ означает начало строки; • $ означает конец строки; •. означает любой символ (т. е. работает как групповой символ); • \ означает " отказ" от специального значения следующего символа (например, \. означает то, что точка является не групповым символом, а обычным символом); • ^ внутри скобок [] означает " нет" (например, [^/] означает " не косая черта". В регулярных выражениях очень легко наделать ошибок. Вот некоторые из наиболее часто встречающихся ошибок, которые могут привести к ненамеренным совпадениям строк: • применение.* в том случае, когда нужно использовать.+ (поскольку.* не может совпасть ни с чем); • отсутствие " отказа" от специального символа, который вы не хотите интерпретировать (например, когда вы указываете. вместо \. и имеете в виду символ точки, а не любой символ). Таким образом, default.htm совпадет с defaulthtm, а default\.htm совпадет только с default.htm; • пропуск ^ или $ (в предположении, что начало или конец подразумеваются), т. е. default\.htmсовпадет с mydefault.html, а Adefault\.htm$ совпадет только с default.htm; • использование " жадных" выражений, которые совпадут со всеми вхождениями (вместо того, чтобы остановиться после первого вхождения). Самый простой способ проиллюстрировать " жадные" выражения – дать пример: RewriteRule ^(.*)/? 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}! ^www\.yourdomain\.com$ [NC] RewriteRule ^(.*)$ http: //www.yourdomain.com/$1 [L, R=301] Обратите внимание на знак восклицания в начале регулярного выражения. Движок перезаписи интерпретирует это как " нет". Для любого имени хоста (кроме http: //www.yourdomain.com) выдается 301-й редирект на эквивалентный канонический URL поддомена www. Флаг [NC] делает условие перезаписи нечувствительным к регистру. Вы можете спросить, где же флаг [QSA] для сохранения строки запроса? При редиректе он не нужен, т. к. в этом случае он просто подразумевается. Если вы не хотите сохранять строку запроса в правиле перезаписи с редиректом, то поставьте в правиле знак вопроса в конец URL назначения: RewriteCond %{HTTP_HOST}! ^www\.yourdomain\.com$ [NC] RewriteRule ^(.*)$ http: //www.yourdomain.com/$1? [L, R=301] Почему мы не используем Ayourdomain\.com$? Рассмотрим: RewriteCond %{HTTP_HOST} ^yourdomain\.com$ [NC] RewriteRule ^(.*)$ http: //www.yourdomain.com/$1? [L, R=301] Это не даст совпадений для доменов с опечатками вроде yourdoamin.com, на которые будут отвечать сервер DNS и виртуальный хост (если предположить, что ошибочно был написан тот домен, который зарегистрировали вы и который принадлежит вам). При каких обстоятельствах вам может понадобиться опустить строку запроса из перенаправленного URL (как мы это делали в предыдущих двух примерах)? Когда нужно опустить идентификатор сеанса или параметр отслеживания (такой, как source=banner_ad1)? Сохранение параметра отслеживания после редиректа не только не нужно (поскольку оригинальный URL с приписанным к нему исходным кодом будет записан в ваших журналах доступа), но и нежелательно с точки зрения канонизации. Что будет, если вы захотите отбросить параметр отслеживания из перенаправленного URL, но сохранить остальные параметры строки запроса? Вот как это можно сделать для статических URL: RewriteCond %{QUERY_STRING} ^source=[a-z0-9]*$ RewriteRule ^(.*)$ /$1? [L, R=301] И для динамических URL: RewriteCond %{QUERY_STRING} ^(.+)& source=[a-z0-9]+(&?.*)$ RewriteRule ^(.*)$ /$1? %1%2 [L, R=301] Хотите до перенаправления пользователя сделать что-то забавное при помощи куки-файлов? Запустите скрипт, который делает куки-файл для пользователя, и затем перенаправьте его 301-м редиректом на канонический URL: RewriteCond %{QUERY_STRING} ^source=([a-z0-9]*)$ RewriteRule ^(.*)$ /cookiefirst.php? source=%1& dest=$1 [L] Обратите внимание на отсутствие в предыдущем коде флага [R=301]. Это сделано специально. Нет необходимости демонстрировать этот скрипт пользователю. Используйте перезапись и пусть скрипт сам отправит 301-й редирект после завершения своей работы. Прочие случаи корректировок проблем канонизации при помощи правил перезаписи и флага [R=301]: • когда поисковые движки индексируют страницы каталогов с указателями HTTPS; • когда в конце URL отсутствует косая черта (которая там должна быть). Сначала корректировка для HTTPS: # redirect online catalog pages in the /catalog/ directory if HTTPS RewriteCond %{HTTPS} on RewriteRule ^catalog/(.*) http: //www.yourdomain.com/catalog/$1 [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 ^get_product\.php$ /products/%1.html? [L, R=301] Однако если вы не будете осторожны, то получите бесконечный цикл рекурсивных редиректов. Быстрый (но некрасивый) способ избежать этого – добавить бессмысленный параметр в URL назначения при перезаписи и обеспечить отсутствие этого бессмысленного параметра перед выполнением редиректа, например: RewriteCond %{QUERY_STRING} id=([0–9]+) RewriteCond %{QUERY_STRING}! blah=blah RewriteRule ^get_product\.php$ /products/%1.html? [L, R=301] RewriteRule ^products/([0–9]+)/? $ /get_product.php? id=$1& blah=blah [L] Обратите внимание, что в примере использованы две строки RedirectCond (одна над другой). Все условия редиректа, перечисленные в одном блоке, будут связаны операцией AND. Если вы хотите, чтобы их связывала логическая операция OR, то придется использовать флаг [OR]. Популярное:
|
Последнее изменение этой страницы: 2016-04-10; Просмотров: 626; Нарушение авторского права страницы