Htaccess rewriterule

Что означают строчки с RewriteCond и RewriteRule в файле .htaccess?
Это директивы (инструкции) преобразования адресов для PHP Zend Framework модуля mod_rewrite. Использование директив модуля mod_rewrite увеличивает нагрузку на сервер!

# Описание инструкции (комментарий до конца строки) RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ index.php [NC,L]

Включение изменения ссылок: RewriteEngine on
Базовый URL для преобразований в каталоге: RewriteBase /
RewriteCond задает условие выполнения преобразований:
REQUEST_FILENAME – Полный путь к файлу или скрипту из запроса
’-s’ файл с ненулевым размером:

RewriteCond %{REQUEST_FILENAME} -s [OR]

или ’-l’ символическая ссылка:


RewriteCond %{REQUEST_FILENAME} -l [OR]

или ’-d’ каталог:

RewriteCond %{REQUEST_FILENAME} -d

RewriteRule задает правило преобразований

^ начало строки
$ конец строки
. любой одиночный символ
* ноль или N предшествующих символов (N > 0)
‘nocase|NC’ не учитывать регистр
‘last|L’ последнее правило

В общем виде, в теории:

Правила

RewriteRule шаблон_поиска строка_замены [флаги]

В шаблоне поиска записывается регулярное выражение для поиска в запрашиваемом URL.
[spoiler title=»Некоторые правила PERL-совместимых регулярных выражений»]
Текст:
. любой символ
[ ] класс: [символы] любые символы класса, [^символы] любые символы кроме символов класса
| или: text1|text2 текст1 или текст2
^ начало строки, $ конец строки
Квалификаторы:
?    0 или 1 вхождение предыдущего символа или группы
*    0 или N вхождений  (N > 0)
+   1 или N вхождений (N > 1)
Группировка:
(текст) группа в левой части, которая в левой части  обозначается  $N (N — порядковый номер группы) (см.
же пример 2),  или группировка для альтернативы text1|text2
Экранирование спецсимволов:
символ если нужно использовать символы, которые имеют специальное значение, такие как  . [ ] ( ) [/spoiler]
В строке замены могут использоваться текст, ссылки на подстроки из шаблона поиска и значения серверных переменных.
Серверные переменные в директивах модуля mod_rewrite записываются в формате
%{имя_переменной), где именем переменной может быть:
server_name – имя веб-сервера, например: www.сайт.ru
server_port – номер порта веб-сервера
document_root – каталог документов верхнего уровня для веб-сайта, например, /usr/host/mysite/html
[spoiler title=»Некоторые другие серверные переменные»]
http_forwarded – переадресованная ссылка
http_host – имя компьютера веб-сервера
http_referer – адрес страницы, с которой выполняется переход на текущую страницу
http_user_agent – веб-клиент, который запросил текущую страницу
remote_addr – IP-адрес посетителя
remote_host – имя компьютера посетителя
request_method – метод запроса при обращении к текущей странице
script_filename – физический путь к запрошенной странице, например: /usr/host/mysite/html/page.php
query_string – параметры запроса к странице, например, id=3&parent=4
request_uri – запрошенный URL.
держит строку запроса после имени сервера, например, /company/test.php?id=3&parent=4
request_filename – то же самое, что и request_uri
time_year – текущий год, time_mon – месяц, time_day– день
time_hour – час, time_min – минута, time_sec – секунда
time_wday – день недели, time – текущее время
[/spoiler]

Условия

RewriteCond контрольная_строка шаблон_поиска [флаги]
Если шаблон поиска найден в контрольной строке (условие выполнено), выполняются директивы, указанные сразу за директивой RewriteCond, или управление переходит к следующему блоку директив.

Примеры:

1. Скрытое и видимое преобразование

RewriteEngine on RewriteBase / RewriteRule ^oldpage.html$ newpage.html [R]

— запрос страницы oldpage.html преобразуется в запрос к странице newpage.html, причем если не указан флаг [R], это будет незаметно посетителю (в адресной строке останется oldpage.html)!


2. Преобразование сайт.ru/~username/ ->  сайт.ru/users/username/

... RewriteRule /~([^/]+)?(/*)/ /users/$1/$2 [R]

Скобки ( ) в левой части обозначают группы по порядку, которые в правой части обозначены $1 и $2.

3. Преобразование в зависимости от типа браузера

RewriteEngine On RewriteBase / RewriteCond %{HTTP_USER_AGENT} Opera RewriteCond %{REQUEST_FILENAME} server.ru/$|server.ru/index.php RewriteRule ^(.*) index_opera.php?%{QUERY_STRING} [L] RewriteCond %{HTTP_USER_AGENT} Netscape13 RewriteCond %{REQUEST_FILENAME} server.ru/$|server.ru/index.php RewriteRule ^(.*) index_netscape.php?%{QUERY_STRING} [L]

Если выполнено первое условие RewriteCond — наличие в заголовке HTTP_USER_AGENT подстроки Opera -, проверяется следующее условие — запрос файла index.php или к корню сайта server.ru без указания имени файла. Если и это условие выполняется, выдается файл для браузера Opera – index_opera.php.
(Флаг [L] означает окончание выполнения директив.)
Если же первое условие не выполнено, управление переходит на следующий блок, который начинается с условия

RewriteCond %{HTTP_USER_AGENT} Netscape

и все происходит аналогично для браузера семейства Netscape

4. Преобразование в зависимости от времени суток

С 7:00 до 19:00 дневной файл page_day.php, а в остальное время ночной файл page_night.php:


RewriteEngine On RewriteBase / RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700 RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900 RewriteRule ^page.php$ page_day.php?%{QUERY_STRING} [L] RewriteRule ^page.php$ page_night.php?%{QUERY_STRING} [L]

5. Запрет для конкретного робота

Директивы файла robots.txt – это только рекомендации для роботов. Гарантированный запрет обеспечивают директивы в файле .htaccess, например:

RewriteEngine On RewriteBase / RewriteCond %{HTTP_USER_AGENT} ^robot RewriteCond %{REMOTE_ADDR} ^196.56.78.18 RewriteRule ^(.*) for_bad_robots.php

Здесь проверяется имя robot, переданное в заголовке user-Agent, а затем IP-адрес, с которого робот пришел на сайт. Если оба условия выполняются, происходит запрос к странице for_bad_robots.php.
Источники:
http://itif.ru/htaccess-dly-zend-framework/
http://web.ixit.ru/pdf/apache/apache_config.pdf
Подробнее: http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#rewriteoptions
Всего просмотров 2,593, сегодня 53

sserjoga.blogspot.com

Директива RewriteRule

Описание: Определяет правила для механизма преобразований
Синтаксис: RewriteRule ШаблонПодстановка
Значение по умолчанию: None
Контекст: server configvirtual hostdirectory.htaccess
Разрешение: FileInfo
Статус: Расширение
Модуль: mod_rewrite
Совместимость: Флаг cookie доступен в Apache 2.0.40 и более поздних.

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

Шаблон это perl совместимое регулярное выражение которое применяется к текущему URL. Здесь под «текущим» подразумевается значение URL когда применяется это правило. Этот URL не обязательно совпадает с первоначально запрошенным URL, потому что любое количество правил возможно уже были применены к нему и соответственно преобразовали его.

Некоторые указания по синтаксису регулярных выражений:

Текст: . Любой одиночный символ [chars] Класс симвлолв: Один из символов [^char.    
вы или для создания обратных связей где N группа, которая может быть использована в RHS директивы RewriteRule с $N) Маркеры: ^ Маркер начала строки $ Маркер конца строки Экранирование: char экранирование конкретного символа (к примеру для указания символов ".[]()" и т.д.)

Более подробную информацию о регулярных выражениях, смотрите в документации по регулярным выражениям Perl («perldoc perlre»).

Кроме того, в mod_rewrite символ отрицания (NOT) (‘!‘) — допускаемый префикс в шаблоне. Это даёт вам возможность инвертировать действие шаблона; ну к примеру скажем: «если текущий URLне совпадает с этим шаблоном«. Это может быть использовано в особых случаях, когда проще найти шаблон для несоответствия, или в качестве последнего правила, работающего по умолчанию.

Примечание

При использовании символа NOT (не) для инвертирования действия шаблона вы не можете иметь сгруппированные части групповых символов в шаблоне. Это невозможно потому что когда нет соответствия шаблону, для групп нет никакого содержимого. В результате, если используются шаблоны с отрицанием, вы не можете использовать $N
в строках подстановок!

Подстановка в правиле преобразования это строка будет подставляться (или будет заменять) вместо оригинального URL, для которого есть совпадение Шаблону. Кроме простого текста вы можете использовать

  1. обратные связи $N на шаблоны в RewriteRule
  2. обратные связи %N на последний соответствующий шаблон в RewriteCond
  3. переменные сервера в качестве проверяемых строк в условиях правил (%{VARNAME})
  4. вызовы запросов к массиву (${mapname:key|default})

Обратные связи это $N (N=0..9) идентификаторы которые заменяются содержимым N-й группы подходящего Шаблона. Переменные сервера Это тоже самое что и СравниваемаяСтрока директивы RewriteCond. Запросы к массиву пришли из директивы RewriteMap там они и объяснены. Эти три типа переменных рассматриваются в порядке, в котором они идут в вышеприведенном списке.

Как уже было упомянуто выше, все правила преобразований применяются с использованием Подстановки (в порядке, в котором они определены в конфигурационном файле). URL полностью заменяется Подстановкой и процесс преобразования идет до тех пор, пока не останется больше никаких правил, если только он не прерван специально, с помощью флага L
— см. ниже.

Существует специальная строка подстановки вида ‘-‘ которая означает: НЕТ подстановки! Звучит глупо? Нет, это полезно для правил преобразования которые только проверяют некоторые URL однако не производят подстановок, т.е., в связке с флагом C (цепочка) возможно иметь более чем один шаблон, применяемый перед проведением непосредственно самой подстановки.

Ещё одно замечание: Вы даже можете создавать URL, содержащие строку запроса, в строке подстановки. Просто используйте вопросительный знак внутри строки подстановки для указания того, следующее за ним содержимое должно быть преобразовано в QUERY_STRING (строку запроса). Когда вы хотите убрать существующую строку запроса, завершайте строку подстановки просто вопросительным знаком.

Примечание

Есть одна особенность: Когда вы предваряете поле подстановки строкой http://
thishost[:thisport], — mod_rewrite отрезает её автоматически. Это автоматическое усечение подразумеваемое при внешнем редиректе URL полезная и важная особенность при использовании в связке с запросами к массивам преобразований генерирующих имя хоста. Взгляните на первый пример, в разделе примеров ниже, чтобы понять это.

Помните

Безусловный внешний редирект на ваш собственный сервер не будет работать с префиксом http://thishost из-за этой особенности. Чтобы использовать такой саморедирект, Вы должны использовать флаг R(см. ниже).

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

[флаги]

в качестве третьего аргумента директивы RewriteRule. Флаги — это разделённый запятыми, следующий список флагов:

  • redirect|R [=code] (вызывает редирект)
    Префикс в Подстановке вида http://thishost[:thisport]/ (создающий новый URL из какого-либо URI) запускает внешний редирект (перенаправление). Если нет накакого кода в подстановке ответ будет с HTTP статусом 302 (ВРЕМЕННО ПЕРЕМЕЩЕН). Если вы хотите использовать другие коды ответов в диапазоне 300-400, просто напишите их в виде числа или используйте одно из следующих символических имён: temp (по-умолчанию), permanent, seeother. Используйте это в директивах, которые должны преобразовывать некие виртуальные URL в реальные и возвращать их клиенту, например, преобразовывать </~> в </u/> или всегда добавлять слэш к /u/user, и т.д.

    Примечание: При использовании этого флага, убедитесь, что поле подстановки, это работающий URL! Если это не так, вы перенаправляете в никуда! И помните, что сам по себе этот флаг, только дополняет URL строкой http://thishost[:thisport]/, и процесс преобразования продолжается. Также, обычно вы хотите остановиться и сделать этот редирект немедленно. Для остановки процесса преобразования, вам также нужно написать флаг ‘L’.

  • forbidden|F (делает URL запрещенным)
    Это делает текущий URL запрещённым, например, клиенту немедленно отправляется ответ с HTTP статусом 403 (ЗАПРЕЩЕНО). Используйте этот флаг в сочетании с соответствующими RewriteConds для блокирования URL по некоторым критериям.
  • gone|G (делает URL «мёртвым»)
    Этот флаг делает текущий URL <мертвым>, т.е., немедленно отправляется HTTP ответ со статусом 410 (GONE). Используйте этот флаг для маркировки <мертвыми> не существующие более страницы.
  • proxy|P (вызвает прокси)
    Этот флаг помечает подстановочную часть как внутренний запрос прокси и немедленно (т.е., процесс преобразования здесь останавливается) пропускает его через прокси модуль. Вы должны убедиться, что строка подстановки это реальный URI (например, типично начинающийся с http://hostname), который может быть обработан прокси модулем Apache. Если это не так, вы получите ошибку от прокси модуля. Используйте этот флаг для того, чтобы добиться более мощной реализации диркетивы ProxyPass, интегрирующей некоторое содержимое на удаленных серверах, в пространство имён локального сервера.

    Примечание: Для того чтобы это использовать убедитесь что у вас есть работающий прокси модуль на вашем сервере Apache. Если вы не знаете этого проверьте есть ли в выводе <httpd -l> строчка mod_proxy.c. Если да, эти возможности доступны mod_rewrite. Если нет, то сначала вы должны пересобрать программу <httpd> с включенным прокси модулем.

  • last|L (последнее правило)
    Остановить процесс преобразования на этом месте и не применять больше никаких правил преобразований. Это соответствует оператору last в Perl или оператору break в языке C. Используйте этот флаг для того, чтобы не преобразовывать текущий URL другими, следующими за этим, правилами преобразований. К примеру, используйте это для преобразования корневого URL из (‘/‘) в реальный, например, ‘/e/www/‘.
  • next|N (следуюший раунд)
    Перезапустить процесс преобразований (начав с первого правила). В этом случае URL снова сопоставляется неким условиям, но не оригинальный URL, а URL вышедший из последнего правила преобразования. Это соответствует оператору next в Perl или оператору continue из языка C. Используйте этот флаг для перезапуска процесса преобразований, т.е., безусловному переходу на начало цикла.
    Однако будьте осторожны, для того чтобы не сделать бесконечный цикл!
  • chain|C (связь со следующим правилом)
    Этот флаг связывает текущее правило со следующим (которое, в свою очередь, может быть связано со следующим за ним, и т.д.). Это имеет следующий эффект: если есть соответствие правилу, процесс продолжается как обычно, т.е., флаг не производит никакого эффекта. Если правило не соответствует условию, все следующие, связанные правила, пропускаются. Например, импользуйте это для удаления <.www> части в конфигурационном правиле контекста каталога работающего когда вы разрешаете внешний редирект (где не должно быть <.www>!).
  • type|T=MIME-тип (принудительно установить MIME тип)
    Принудительно установить MIME-тип целевого файла в MIME-тип. К примеру, это можно использовать для имитации mod_alias директивы ScriptAlias которая принудительно устанавливает для всех файлов внутри отображаемого каталога MIME тип равный <application/x-httpd-cgi>.
  • nosubreq|NS (используется только в случае невнутреннего подзапроса)
    Этот флаг дает команду механизму преобразований пропустить директиву если текущий подзапрос является внутренним подзапросом. К примеру, внутренние подзапросы в Apache происходят тогда, когда mod_include пытается получить информацию о возможных файлах по-умолчанию для каталогов (index.xxx). При подзапросах это не всегда полезно и даже иногда вызывает проблему в работе всего набора директив преобразований. Используйте этот флаг для исключения некоторых правил.

    Используйте следующее правило по своему усмотрению: всякий раз когда вы предваряете некоторые URL префиксом передавая их на обработку CGI-скрипту, — велик шанс что вы напоретесь на проблемы (или даже на ненужные издержки) в случае применения подзапросов. В этих случаях, используйте этот флаг.

  • nocase|NC (не учитывать регистр)
    Это делает Шаблон нечуствительным к регистру, т.е., нет различий между ‘A-Z’ и ‘a-z’ когда Шаблон применяется к текущему URL.
  • qsappend|QSA (добавлять строку запроса)
    Этот флаг указывает механизму преобразований на добавление а не замену, строки запроса из URL к существующей, в строке подстановки. Используйте это когда вы хотите добавлять дополнительные данные в строку запроса с помощью директив преобразований.
  • noescape|NE (не экранировать URI при выводе)
    Этот флаг не даёт mod_rewrite применять обычные правила экранирования URI к результату преобразования. Обычно, специальные символы (такие как ‘%’, ‘$’, ‘;’, и так далее) будут экранированы их шестнадцатиричными подстановками (‘%25’, ‘%24’, и ‘%3B’, соответственно); этот флаг не дает это делать. Это позволяет символам процента появлятся на выходе, как в

    RewriteRule /foo/(.*) /bar?arg=P1%3d$1 [R,NE]

    для которого ‘/foo/zed‘ преобразовывалось бы в безопасный запрос ‘/bar?arg=P1=zed‘.

  • passthrough|PT (пропускать через следующий обработчик)
    Этот флаг даёт команду механизму преобразований устанавливать поле uri внутренней структуры request_rec равным полю filename. Этот флаг, просто лишь хитрый трюк, для того чтобы иметь возможность обработки вывода директив RewriteRule, директивами Alias, ScriptAlias, Redirect, и т.д. из других трансляторов URI-имя файла. Тривиальный пример для показа этой семантики: если вы хотите преобразовать /abc в /def с использованием механизма преобразований mod_rewrite и затем /def в /ghi с использованием mod_alias:

    RewriteRule ^/abc(.*) /def$1 [PT]
    Alias /def /ghi

    Если вы опустите флаг PT, mod_rewrite прекрасно сделает свою работу, т.е., он преобразует uri=/abc/... в filename=/def/... как должен делать полностью API-совместимый транслятор URI-имя файла. Затем настаёт очередь mod_alias пытающегося сделать переход URI-имя файла который и не будет работать.

    Примечание: Вы должны использовать этот флаг если вы хотите смешивать директивы разных модулей содержащих трансляторы URL-имя файла. Типичный пример это использование модулей mod_alias и mod_rewrite..

    Для любителей поковыряться в Apache

    Если бы текущий Apache API имел какой-нибудь перехватчик имя файла-имя файла в дополнение к перехватчику URI-имя файла нам бы не понадобился данный флаг! Однако без такого перехватчика этот флаг это единственное решение. The Apache Group обсудила эту проблему и добавит такой перехватчик во 2-й версии Apache.

  • skip|S=количество (пропустить следующее правило(а))
    Этот флаг указывает механизму преобразований пропускать следующее количество правил в последовательности начинающейся с текущего правила. Используйте это для создания псевдо if-then-else конструкций: Последнее правило блока then будет skip=N где N количество правил блока else. (Это не то же самое что и флаг ‘chain|C’!)
  • env|E=VAR:VAL (установить переменную окуржения)
    Присваивает переменной окружения VAR значение VAL, где VAL может содержать обратные связи $N и %N ссылающиеся на части регулярных выражений, которые будут раскрыты соответствующим образом. Вы можете использовать этот флаг более одного раза чтобы присвоить значение более чем одной переменной. Позже, эти переменные могут быть использованы во многих ситуациях, обычно в XSSI (через <!--#echo var="VAR"-->) или в CGI скриптах (например$ENV{'VAR'}). Кроме того, вы можете это использовать в следующем шаблоне RewriteCond через %{ENV:VAR}. Используйте это для удаления, но запоминания некоторой информации из URL.
  • cookie|CO=NAME:VAL:domain[:lifetime[:path]] (записать cocookie)
    Записывает cookie клиенту. Имя cookie указывается в NAME а его значение в VAL. Поле domain это домен cookie, такой как например ‘.apache.org’, опциональное lifetime это время жизни cookie в минутах, и опциональный path это путь cookie

Примечание

Никогда не забываёте что Шаблон применяется ко всему URL в конфигурационных файла сервера. Однако в конфигурационных файлах каталогов, префикс каталога (который всегда одинаков для конкретного каталога !), автоматически удаляется при соответствии шаблону и автоматически добавляется после завершения подстановки. Эта особенность, основа для многих видов преобразований, потому что без удаления префикса для родительского каталога тоже должно быть соответствие, что не всегда возможно.

Есть одно исключение: Если строка подстановки начинается с <http://> в этом случае префикс каталога не добавляется и происходит либо внешний редирект либо пропускание через прокси (если используется флаг P!)!

Примечание

Для того чтобы включить механизм преобразований в конфигурационных файлах каталогов вам нужно написать <RewriteEngine On> в этих самых файлах и, кроме того, должна быть разрешена конфигурационная директива <Options FollowSymLinks>. Если ваш администратор запретил перегрузку конфигурационной директивы FollowSymLinks в пользовательских каталогах, в этом случае вы не сможете использовать механизм преобразований. Это ограничение нужно по соображениям безопасности.

Вот все возможные комбинации подстановок с расшифровкой их значений:

В конфигурационных файлах контекста сервера (httpd.conf)
для запроса вида <GET /somepath/pathinfo>:

Правило Подстановка  ---------------------------------------------- ---------------------------------- ^/somepath(.*) otherpath$1 не поддерживается, т.к. неверно!  ^/somepath(.*) otherpath$1 [R] не поддерживается, т.к. неверно!  ^/somepath(.*) otherpath$1 [P] не поддерживается, т.к. неверно! ---------------------------------------------- ---------------------------------- ^/somepath(.*) /otherpath$1 /otherpath/pathinfo  ^/somepath(.*) /otherpath$1 [R] http://thishost/otherpath/pathinfo  через внешний редирект  ^/somepath(.*) /otherpath$1 [P] не поддерживается, - глупо! ---------------------------------------------- ---------------------------------- ^/somepath(.*) http://thishost/otherpath$1 /otherpath/pathinfo  ^/somepath(.*) http://thishost/otherpath$1 [R] http://thishost/otherpath/pathinfo  через внешний редирект  ^/somepath(.*) http://thishost/otherpath$1 [P] не поддерживается, - глупо! ---------------------------------------------- ---------------------------------- ^/somepath(.*) http://otherhost/otherpath$1 http://otherhost/otherpath/pathinfo  через внешний редирект  ^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo  через внешний редирект  (флаг [R] избыточен)  ^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo  через внутренний прокси 

Внутри конфигурационного файла каталога, для /somepath
(т.е., файл .htaccess в каталоге /physical/path/to/somepath содержит RewriteBase /somepath)
для запроса <GET /somepath/localpath/pathinfo>:

Правило Подстановка ---------------------------------------------- ---------------------------------- ^localpath(.*) otherpath$1 /somepath/otherpath/pathinfo  ^localpath(.*) otherpath$1 [R] http://thishost/somepath/otherpath/pathinfo  через внешний редирект  ^localpath(.*) otherpath$1 [P] не поддерживается, - глупо! ---------------------------------------------- ---------------------------------- ^localpath(.*) /otherpath$1 /otherpath/pathinfo  ^localpath(.*) /otherpath$1 [R] http://thishost/otherpath/pathinfo  через внешний редирект  ^localpath(.*) /otherpath$1 [P] не поддерживается, - глупо! ---------------------------------------------- ---------------------------------- ^localpath(.*) http://thishost/otherpath$1 /otherpath/pathinfo  ^localpath(.*) http://thishost/otherpath$1 [R] http://thishost/otherpath/pathinfo  через внешний редирект  ^localpath(.*) http://thishost/otherpath$1 [P] не поддерживается, - глупо! ---------------------------------------------- ---------------------------------- ^localpath(.*) http://otherhost/otherpath$1 http://otherhost/otherpath/pathinfo  через внешний редирект  ^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo  через внешний редирект  (флаг [R] избыточен)  ^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo  через внутренний прокси 

htmlweb.ru

В последнее время мне стало интересно изучать низкоуровневые подходы минуя тот функционал, который предлагают нам фреймворки. Таким образом, я открываю для себя новые знания в программировании. Когда-то я проходил все стадии написания «велосипедов», но чтобы быть нормальным проггером, нужно знать как там всё устроено, это нормально. Сегодня рассмотрим перенаправления с помощью файла .htaccess для веб-сервера Apache на небольшом примере.

Чтобы не томиться ожиданием, давайте сразу перейдём к задаче: нужно сделать перенаправление со страницы /pages/about.php на /about, т. е. убрать в адресе папку /pages и расширение .php в названии файла. Ещё нужно позаботиться о том, чтобы в конце URL не было закрывающего слеша. Вот такую файловую структуру содержит наш пример:

В Apache для преобразования URL’ов есть специальный модуль mod_rewrite. Он отвечает за создание ЧПУ — создаёт красивые URL для PHP-скриптов на уровне веб-сервера. Его мы и задействуем для решения нашей задачи. Для начала создадим конфигурационный файл .htaccess в корне сайта со следующим содержимым, а затем я объясню как он отработает:

Командой RewriteEngine On мы включаем модуль mod_rewrite, а с помощью RewriteRule задаём правила преобразования адресов. RewriteRule просто преобразует входной URL по порядку в соответствии с регулярными выражениями. В конце каждого правила можно задать флаги для указания поведения mod_rewrite при обработке URL. Синтаксис прост как три копейки:

Давайте разберём первое правило из примера: ^(.*)/$ /$1 [L,R=301] — между маркерами ^ и $ мы указали начало строки с любого символа и любой длины (.*), где конец строки должен заканчиваться на слеш /. Всё, что заключено в круглые скобки (.*) образует группу символов, которую можно использовать через макрос $1.

Теперь все URL’ы, которые заканчиваются на слеш, будут переброшены на адрес без последнего слеша, где /$1 — все входные символы без последнего слеша. Флаг [L] останавливает чтение .htaccess, а [R=301] генерирует HTTP-код ответа сервера HTTP/1.1 301 Moved Permanently. После того, как правило отработало и Apache обрезал закрывающий слеш, файл .htaccess выполнится ещё раз и первое правило больше не отработает.

Второе правило: ^(w+)$ /pages/$1.php [L,NC] — пользователь запросит адрес страницы, который имеет буквенное или цифровое содержимое от одного и больше символов (w+). Это образует группу символов, которые мы подставим в адрес скрипта /pages/$1.php. По факту выполниться скрипт под другим URL. Флаг [L] останавливает .htaccess, а [NC] отменяет проверку регистра символов.

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

denisyuk.by

Редиректы

Редиректы осуществляются с помощью модуля mod_rewrite. Задаются правила преобразований в виде следующей конструкции:

  <IfModule mod_rewrite.c>   Options +FollowSymLinks   RewriteEngine On     [СЮДА ПИШЕМ ПРАВИЛА]     </IfModule>  

Правила преобразования записываются в таком виде:

  RewriteCond [СТРОКА ДЛЯ СРАВНЕНИЯ] [УСЛОВИЕ] [ФЛАГИ]  RewriteCond [СТРОКА ДЛЯ СРАВНЕНИЯ] [УСЛОВИЕ] [ФЛАГИ]  RewriteRule [ШАБЛОН] [СТРОКА ПОДСТАНОВКИ] [ФЛАГИ]  

Строки RewriteCond — задают условия для срабатывания следующего за ними правила RewriteRule. Условий может быть несколько, они накладываются по правилу AND. Но можно изменить правило на OR с помощью флага OR.

В качестве [СТРОКИ ДЛЯ СРАВНЕНИЯ] могут использоваться различные переменные. Ссылка на полный список Я приведу только те, которые нужны чаще всего:

%{REQUEST_URI} Строка запроса (без доменного имени, и GET параметров), пример «/server/htaccess/»
%{HTTP_HOST} Доменное имя, например «max22.ru»
%{QUERY_STRING} Строка GET параметров

[УСЛОВИЕ] также как и [ШАБЛОН] представляют собой perl совместимое регулярное выражение, с некоторыми дополнениями, позволяющими например проверить файл ли это, или существующий url.

[ФЛАГИ] Флаги пишутся в квадратных скодках через запятую: [NC,OR]. Флаги для условий:

NC Регистронезависимая проверка
OR Условие сопостовляется с остальными про правилу ИЛИ

Подвыражения в регулярных выражениях (заключенные в скобки), доступны для вставки в [СТРОКУ ПОДСТАНОВКИ], обращаться к подвыражениям нужно так: %N — для подвыражений в условиях (RewriteCond) и $N — для подвыражений в правилах (RewriteRule), где N — порядковый номер подвыражения.

RewriteRule — правило подстановки. Если запрос подходит под вышестоящие проверки и [ШАБЛОН], то применяется правило подстановки. Здесь регулировать поведение также можно с помощью флагов. Флаги есть разные, приведу наиболее часто используемые:

NC Регистронезависимая проверка
R=301 Будет редирект с кодом 301, можно указать другой код
L Это последнее правило, больше не применять правил преобразований

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

Внимание! Браузеры кешируют редиректы!!!

Причем обычные сочетания типа Ctrl+F5 или Ctrl+R не помагают. Я во время тестирования каждый раз открываю страницу в НОВОМ окне в режиме инкогнито. Причем старые страницы в режими инкогнито надо закрывать.

max22.ru

Самые жирные функции, которые можно реализовать с помощью mod_rewrite

1. Создание «Дружественных» URL адресов, которые используются для маскировки «кривых» URL

При написании скрипта example.php, например, для вывода статей, вы можете оформить ссылку на статью, используя такой URL:

Данный URL выглядит некрасиво и запрос (?exapleId=my-example) может вызывать недоумение у поисковых механизмов. Лучше использовать URL следующего вида:

Преобразовать URL в таком случае нам поможет mod_rewrite. Что нам нужно сделать? В корне сайта находится файл .htaccess, допишем в него:

  RewriteEngine on  RewriteRule ^articles/([^/]+)/?$ example.php?exampleId=$1 [L]  

Теперь рассмотрим правило RewriteRule подробнее:

  • ^articles/([^/]+)/?$ — регулярное выражение, имеющее соответствие с любым URL адресом в формате articles/ (articleID)/. Оно подразумевает: «соответствие началу URL адреса, за которым будет текст (articles/), вслед за которым будет один или много символов, предшествующих слэшу ([^/]+), за которыми будет следовать собственно слэш (/?), за которым будет символ окончания URL ($)».
  • example.php?exampleId=$1 – эта часть говорит серверу использовать скрипт example.php , которому отправляется текст, соответствующий подшаблону [^/]+ из регулярного выражения.
  • [L] — Флаг для прекращения последующей обработки этого URL адреса.

 

2. Блокировка возможности использования ссылок в изображениях на сайте

Также модуль mod_rewrite может запретить использовать ссылки на изображения. Допустим, существует страница вашего сайта //semantica.in/page.html, в которой содержится такой тег img:

Любой другой ресурс может позаимствовать вашу картинку:

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

Чтобы избежать таких проблем, в файле .htaccess дописываем:

 

  RewriteEngine on    RewriteCond %<HTTP_REFERER> !^$    RewriteCond %<HTTP_REFERER> !^http://(www.)?semantica.in/.*$ [NC]    RewriteRule .+.(gif|jpg|png)$ - [F]  

Разберем как работает этот код:

  • RewriteEngine on — включаем mod_rewrite
  • RewriteCond %<HTTP_REFERER> !^$- RewriteCond — директива mod_rewrite. Директива устанавливает условие, которое выполняется для обработки URL следующим правилом RewriteRule. В нашем случае условием будет значение в переменной HTTP_REFERER.
  • RewriteCond %<HTTP_REFERER> !^http://(www.)?semantica.in/.*$ [NC] — вторая директива ставит условие — значение переменной HTTP_REFERER не должно начинаться с http://www.semantica.in/ или //semantica.in/. [NC] — флаг устанавливает чувствительность к регистру символов.
  • RewriteRule .+.(gif|jpg|png)$ — [F]— правило пропускается, если два условия RewriteCond не выполнены. Само же правило возвращает ошибку «403 Forbidden»

 

3. Исключение ошибки 404 в период реорганизации сайта

При реорганизации содержания сайта, возможно изменение URL страницы. В этом случае, в выдаче новый URL появится через какое-то время. Получается, что при переходе по старой ссылке из выдачи поисковика или какого-нибудь ссылающегося сайта, пользователь увидит ошибку 404.

Здесь нам опять поможет модуль Apache mod_rewrite, предназначенный для реализации 301 редиректа. HTTP отсылает браузеру старый адрес, информируя, что у страницы новый адрес URL.

Необходимо дописать в файл .htaccess:

  RewriteEngine on  RewriteRule ^semantica.html$ /new_semantica.html [R=301,L]  

 

Далее рассмотрим подробнее как работает правило RewriteRule в этом случае:

  • ^semantica.html$ — регулярное выражение, значению которого соответствует старый адрес URL страницы. Значение шаблона: «соответствует началу адреса (^), за которым будет текст ‘ semantica.html’, за которым будет символ окончания адреса ($).»
  • /new_semantica.html — вторая часть описывает, на какое выражение нужно менять. В нашем случае это /new_semantica.html.
  • [R=301,L] — используется 2 флага: R=301 означает «301 редирект на новый URL»; L – флаг для прекращения последующей обработки этого URL адреса.

 

 

Разберем подробнее как работает mod_rewrite

Итак, вы поняли (надеюсь), что такое mod_rewrite. Теперь самое время познакомится с директивой RewriteRule.  Эта директива может встречаться много раз, и каждый раз будет определять новое правило преобразования.

Чтобы понять как работает RewriteRule, необходимо знать с чем он работает. Для этого рассмотрим, как Apachе получает строку, которая передается на обработку RewriteRule в .htaccess.

Поначалу кажется, что mod_rewrite работает с ссылками, но в случае mod_rewrite htaccess это не так. 

Из-за своей внутренней архитектуры сервер Apache в момент, когда работает .htaccess, mod_rewrite, может манипулировать путем файла, который должен быть обработан. Это происходит из-за других модулей, которые могли изменить запрос до передачи в модуль. Поэтому в mod_rewrite передается абсолютный путь файла. А также модуль знает путь до .htaccess в котором заданы правила RewriteRule. Для того чтобы из пути сделать ссылку, модуль отрезает от абсолютного пути часть до .htaccess.

Путь, от которого отрезан .htaccess, передается в первый rewriteRule. Пример:

  • Запрос: //semantica.in/wp-content/themes/semantica/i/sidebar/logo.png
  • Documentroot: /var/www/semantica.in
  • Путь файла: /var/www/semantica.in/wp-content/themes/semantica/i/sidebar/logo.png
  • Путь .htaccess: /var/www/semantica.in/ wp-content/.htaccess
  • В первый RewriteRule передается: themes/semantica/i/sidebar/logo.png

 

 

Важно помнить то, что RewriteRule не обрабатывает аргументы, которые не переданы в скрипт, имя сайта, ссылку, кстати, тоже обрабатывает не всю, если .htaccess лежит не в корне. Для этого существует другой модуль.

semantica.in

Автор: Патрик Элтофт
Перевод: Всеволод Козлов

Несмотря на то, что статей и руководств, освещающих .htaccess и mod_rewrite, в Сети, мягко говоря, немало, многие веб-мастера до сих пор испытывают нехватку знаний по этому вопросу. Многим из них просто непонятно то, что говорится в этих мануалах, т.к. там это все сложно для их понимания.

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

Не будем терять времени, приступаем!

Сперва давайте разберемся, что же такое файл .htaccess и mod_rewrite.

.htaccess – файл-конфигуратор Apache-серверов.

Mod_rewrite – модуль, используемый веб-серверами для преобразования URL’ов.

.htaccess представляет собой обычный текстовый документ, расширение которого htaccess. Данный файл обычно находится в корне сайта, однако Вы можете создавать и дополнительные .htaccess-файлы для различных директорий Вашего сайта.

Удаление дублей страниц

Простейший и в то же время чаще всего необходимый трюк – редирект дублей одной и той же страницы на основной ее адрес.

Яркий пример – главная страница любого сайта обычно доступна по 4-ем адресам:

  • http://www.site.ru/
  • http://site.ru/
  • http://www.site.ru/index.html
  • http://site.ru/index.html

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

Решение этой проблемы предельно простое и выглядит так:

Options +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^site.ru
RewriteRule (.*) http://www.site.ru/$1 [R=301,L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9} /index.html HTTP/
RewriteRule ^index.html$ http://www.site.ru/ [R=301,L]

Таким образом, мы получим редирект всех страниц-дублей на http://www.site.ru/

Меняем расширение html на php

Иногда бывает так, что у Вас статичный веб-сайт, а Вам необходимо, чтобы на нем срабатывал какой-нибудь php-скрипт. Для этого Вам необходимо сказать серверу, чтобы он обрабатывал эту страницу как php-файл.

AddHandler application/x-httpd-php .html

Этот прием можно использовать и для других расширений файлов:

AddHandler application/x-httpd-php .xml
AddHandler application/x-httpd-php .asp

Задаем собственные страницы ошибок

О необходимости создания собственной страницы ошибок я уже неоднократно рассказывал:

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

Задать же собственную страницу ошибок можно следующим образом:

ErrorDocument 404 http://www.site.ru/404.php

Индексация директорий и поддиректорий

Чтобы избежать индексации поисковыми системами директорий и поддиректорий, необходимо прописать такую строку, к примеру:

DirectoryIndex index.php3

Лично я предпочитаю переадресовывать с пустых директорий либо на главную страницу сайта, либо на какую-либо другую подходящую страницу. Например, директорию www.site.ru/images/ можно переадресовать на www.site.ru, а www.site.ru/forum/ на www.site.ru/forum/index.php.

Переадресация страниц

Простое правило, позволяющее переадресовывать с одной страницы на другую:

redirect 301 /old-page.php http://www.site.ru/new-page.php

Переадресация Вашего фида на Feedburner

Если Вы хотите, чтобы на Ваш RSS-фид подписывались через Feedburner, то используйте следующий код:

RewriteCond %{HTTP_USER_AGENT} !FeedBurner
RewriteRule ^your-feed.xml$ http://feeds.feedburner.com/your-feed [R,L]

Защита изображений от скачивания

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

RewriteEngine on
RewriteCond %{HTTP_REFERER} .
RewriteCond %{HTTP_REFERER} !^http://([^.]+.)?site. [NC]
RewriteCond %{HTTP_REFERER} !google. [NC]
RewriteCond %{HTTP_REFERER} !search?q=cache [NC]
RewriteCond %{HTTP_REFERER} !msn. [NC]
RewriteCond %{HTTP_REFERER} !yahoo. [NC]
RewriteCond %{REQUEST_URI} !^/hotlinker.gif$
RewriteRule .(gif|jpg|png)$ /hotlinker.gif [NC,L]

hotlinker.gif – изображение, которое будет отображаться у нерадивых веб-мастеров, вместо истинных изображений. Рекомендую в этом изображении отобразить Ваш логотип и ссылку на Ваш сайт.

Создание ЧПУ (человеко-понятных урлов) с помощью mod_rewrite

C его помощью можно преобразовать, например, www.site.ru/product.php?id=123 в www.site.ru/product/123 следующим образом:

RewriteEngine on
RewriteRule ^product/([^/.]+)/?$ product.php?id=$1 [L]

В другом примере преобразуем www.site.ru/script.php?product=123 в www.site.ru/cat/product/123/:

RewriteRule cat/(.*)/(.*)/$ /script.php?$1=$2

Избавляемся от QUERY_STRING

Некоторые веб-мастера делают ссылки вида www.site.ru/index.php?source=blogstorm, чтобы знать, откуда идут посетители. Из-за этого появляется дублированный контент, от которого надо избавляться:

RewriteCond %{QUERY_STRING} ^source= RewriteRule (.*) /$1? [R=301,L]

www.seoschool.ru

У меня RewriteEngine всегда был довольно стрессовой темой. Только вот недавно я вдруг обнаружил, что все как-то улеглось и стало более или менее понятно. Поскольку я совершенно обычный человек, я уверен, что ситуация ошибки конфигурации веб-сервера «доставала» не одного лишь меня, и я спешу поделиться своим опытом.

Получилось нечто среднее между руководством по использованию модуля mod_rewrite и своеобразным справочником по конфигурированию веб-сервера с помощью файла .htaccess. Попутно хотелось бы заострить внимание на особо сложных или неочевидных моментах.

Предполагается, что читатель использует урл-рерайтинг в своей работе, знает, в общих чертах, что такое RewriteEngine и уже провел несколько часов за его настройкой. Эта статья не совсем для начинающих, но и не для супер-профи, конечно.

Исходные данные для опытов

  • Все опыты производятся на локальном хосте.
  • Установлен сервер lampp
  • Версия Apache: 2.4.9 (сборка для Unix)
  • В папке /opt/lampp/htdocs/bbb/_engine лежит опытный сайт на домене engine.bbb.ru. Указанная папка является корневой (DocumentRoot).
  • В корневой папке сайта лежит всего одна страница ind.php.
  • На сайте есть одна папка /opt/lampp/htdocs/bbb/_engine/local.
  • В ней лежит один скриптовый файл ind1.php

Настройка виртуальных хостов

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

Настраиваем логи

Мало у кого на локальном сервере всего один домен. Доменов обычно много. Хорошо бы разделить логи по доменам и по дням, чтобы они не слишком разрастались. Делается это через раздел <VirtualHost> настроек нашего сервера.

Для лога ошибок на нашем домене добавляем следующие две строчки.

 ErrorLog "|/opt/lampp/bin/rotatelogs /opt/lampp/logs/engine-bbb-error.%Y.%m.%d.log 86400"  LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i"" combined 

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

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

Для лога доступа я у себя включаю только одну строчку. Формат строки «по умолчанию» меня обычно устраивает.

 CustomLog "|/opt/lampp/bin/rotatelogs /opt/lampp/logs/engine-bbb-access.%Y.%m.%d.log 86400" combined 

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

Самые общие сведения о том, как все работает

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

RewriteEngine on 

в файле .htaccess, который будет управлять этой папкой. Кроме этого мы располагаем ниже этой строчки другие директивы и несколько правил для рерайтинга.

Предположим, сервер получает на вход некий урл. RewriteEngine начинает этот урл проверять, используя правила. Делает он это сверху вниз по порядку. Если входной урл НЕ УДОВЛЕТВОРЯЕТ ни одному правилу, то он, что называется «проходит». Так, например, предположим, что у нас есть в корневой папке файл index.php. Если входной ури "/index.php" не удовлетворяет ни одному правилу, то мы увидим в браузере результат работы этого скрипта.

Если мы имеем следующее правило

RewriteRule ^index.php$ / [L] 

то, очевидно, это правило для ури «index.php» сработает. В этом случае ури будет переписан на "" и новый ури "/" будет послан на вход серверу. И весь процесс применения правил пойдет заново. Только в том случае, если ури "/" не удовлетворит ни одному нашему правилу, мы увидим то, что хотим. А если удовлетворит, то он будет опять переписан и все повторится заново.

Как работает флаг [L]

Наверное, этот флаг вносит особенно много недопониманий. Наличие флага предотвращает проверку входного ури на следующие за ним правила, если это правило сработало. Только и всего. То есть, если наш ури «index.php» прошел проверку (правило для него сработало), то ввиду наличия флага [L] мы прерываем все последующие проверки, и веб сервер сразу производит рерайтинг «index.php» -> "" и получает на вход ури "/" ([INTERNAL REDIRECT] ), и все повторяется с начала, с первого правила. А если этого флага нет, то рерайтинг все равно происходит и проверка продолжается со следующего правила. Но ури будет уже измененный, а именно "/".

Понимание этого процесса сразу предотвращает много циклических редиректов.

Но позвольте, не значит ли написанное выше, что если не использовать флаг [L], мы сэкономим время и страница откроется быстрее? Мы натыкаемся на флаг [L] и должны пройти заново по всем правилам без исключения, а если не ставить флаг [L], то мы сделаем рерайтинг на сработавшем правиле, пройдем до конца всех правил и на этом закончим?

Я проверил. Это не срабатывает. В случае отсутствия флагов [L], модуль, как и предполагается, заменяет ури на сработавшем правиле, идет по всем оставшимся правилам до конца, потом производит [INTERNAL REDIRECT] и все равно проходит с этим ури все правила еще раз. То есть подтверждается то, о чем мы писали выше. Это правило, похоже, не имеет исключений.

Вывод: всегда, когда срабатывает правило RewriteRule, происходит [INTERNAL REDIRECT] и повторное применение всех правил. Этот второй проход начинается либо сразу после применения правила с флагом [L], или после того, как кончатся все правила, если работаем без флагов [L]. Ситуация «прохода» урла, a она называется «pass through» может произойти только в том случае, если ни одно правило не было применено. Флаг [L] действительно может уменьшить время обработки ури и его следует использовать везде, где возможно.

Что есть RewriteBase?

Эта инструкция, на мой взгляд, просто рекордсмен по непонятности! Я бы дал ей за это приз! Ввиду этого у меня есть две истории про этого зверя — короткая и длинная. Короткая история для тех, кто не хочет на эту инструкцию заморачиваться. Длинная для интересующихся.

Короткая история

Если вы занимаетесь относительно простым урл-рерайтингом с помощью файлов .htaccess, то рекомендую всегда поступать следующим образом.

  • Не использовать описываемую директиву вообще.
  • Во всех правилах рерайтинга целевой урл всегда начинать со слэша (указание на то, что ури указывается относительно корня сайта)
Длинная история

При рерайтинге будут происходить следующие процессы:

Имеем:

  • Document Root: /opt/lampp/htdocs/bbb/_engine
  • Файл .htaccess лежит там же, в Document Root

Мы запрашиваем урл engine.bbb.ru/ind.php

  • Сервис рерайтинга приведет путь запрашиваемого файла к его пути в файловой системе, а именно opt/lampp/htdocs/bbb/_engine/ind.php
  • Удалит из него префикс opt/lampp/htdocs/bbb/_engine/ (совпадает с путем к папке, в которой лежит .htaccess)
  • Будет применять правила рерайтинга, используя строку «ind.php»

Если в папке /opt/lampp/htdocs/bbb/_engine/local нет файла .htaccess или есть, но в нем не включен RewriteEngine

  • Мы запрашиваем урл engine.bbb.ru/local/ind1.php
  • Сервис рерайтинга приведет путь запрашиваемого файла к его пути в файловой системе, а именно opt/lampp/htdocs/bbb/_engine/local/ind1.php
  • Удалит из него префикс opt/lampp/htdocs/bbb/_engine/
  • Будет применять правила рерайтинга, используя строку «local/ind.php»

Если в папке /opt/lampp/htdocs/bbb/_engine/local есть файл .htaccess и в нем включен RewriteEngine

  • Мы запрашиваем урл engine.bbb.ru/local/ind1.php
  • Сервис рерайтинга приведет путь запрашиваемого файла к его пути в файловой системе, а именно opt/lampp/htdocs/bbb/_engine/local/ind1.php
  • Удалит из него префикс opt/lampp/htdocs/bbb/_engine/local/ (это путь к папке, где лежит файл .htaccess директории /local)
  • Будет применять правила рерайтинга, используя строку «ind1.php»

Внимание! Такой алгоритм будет выполняться всегда. Этот алгоритм выражает специфику термина "per-dir", то есть "по-директорного" подхода, заложенного в сервере Apache. Значение директивы RewriteBase никак на него (на алгоритм) не влияет.

На что же влияет директива RewriteBase?

Нужно очень хорошо помнить, что в директиве RewriteBase указывается URL! Нельзя указать там "local/" Будет ошибка! Можно только "/local".

Пусть в нашем /opt/lampp/htdocs/bbb/_engine/local/.htaccess мы указали

RewriteBase /local 

Мы запрашиваем урл engine.bbb.ru/local/

Тогда правило

RewriteRule ^$ ind1.php 

Сработает! И будет осуществлен переход на ури /local/ind1.php

А правило

RewriteRule ^$ /ind1.php 

тоже сработает, но переход будет осуществлен на ури /ind1.php. Файл не найден! Такого ури (относительно корня сайта) у нас нет!

Вывод 1: URL, который мы указываем в RewriteBase добавляется в качестве префикса к целевому ури в том случае, если он является относительным, то есть в начале нет слэша.

Вывод 2: Если мы никогда не используем относительные целевые ури в правилах, то и директива RewriteBase нам не нужна!

Вывод 3: Если мы используем «RewriteBase /», то при срабатывании правила

RewriteRule ^$ ind1.php 

Будет попытка прейти на ури /ind1.php. Мы просто используем "/" в качестве префикса.

Как я получил все эти захватывающие дух сведенья об интимной жизни сервера Apache? Или наконец-то об отладке

Действительно! Как я увидел ошибки, который выдает сервис переименования урлов? Ведь именно это и есть отладка! Есть очень полезная директива, которую я вставил в виртуальные хосты для домена engine.bbb.ru. А именно

 LogLevel warn rewrite:trace4 

После вставки я перезагрузил Apache. И с этого момента в лог ошибок домена, а именно в файл /opt/lampp/logs/engine-bbb-error.2015.08.08.log стали вставляться строки трассировки, относящиеся к модулю rewrite. Строк много. Почему trace4? Может быть можно вставить trace3? Можно. Но тогда нельзя будет отладить RewriteCond, не будет детальной информации что и с каким паттерном мы сравниваем и пропадет информация о некоторых других событиях (не столько важных, сколько интересных).

А что такое "warn"? Буквально наша запись LogLevel означает, что для всех модулей уровень ошибок warn и только для модуля rewrite — trace4

Что мы получаем в результате включения отладки?

Получаем трассировку, или очень-очень подробный лог. Трассировочных строк действительно много. Если я попадаю в сложный затык с правилами, и после какого-то времени мучений у меня ничего не получается, и я принимаю решение включить трассировку, то я в своем .htaccess отключаю все правила, которые не относятся к испытуемому урлу. Ставлю перед ними знак комментария "#". После этого перезагружаю страницу, которая не работает и стараюсь найти нужные строки в логе.

Представляю трассировку рерайтинга со следующими условиями:

Запрашиваем:

http://engine.bbb.ru/

Правила:

RewriteEngine on  RewriteRule ^$ /ind.php [L] 
[Sat Aug 08 15:41:38.664920 2015] [rewrite:trace3] [pid 21776] mod_rewrite.c(475): [client 127.0.0.1:45382] 127.0.0.1 - - [engine.bbb.ru/sid#85a910][rid#dd7890/initial] [perdir /opt/lampp/htdocs/bbb/_engine/] strip per-dir prefix: /opt/lampp/htdocs/bbb/_engine/ ->  [Sat Aug 08 15:41:38.664955 2015] [rewrite:trace3] [pid 21776] mod_rewrite.c(475): [client 127.0.0.1:45382] 127.0.0.1 - - [engine.bbb.ru/sid#85a910][rid#dd7890/initial] [perdir /opt/lampp/htdocs/bbb/_engine/] applying pattern '^$' to uri '' [Sat Aug 08 15:41:38.664960 2015] [rewrite:trace2] [pid 21776] mod_rewrite.c(475): [client 127.0.0.1:45382] 127.0.0.1 - - [engine.bbb.ru/sid#85a910][rid#dd7890/initial] [perdir /opt/lampp/htdocs/bbb/_engine/] rewrite '' -> '/ind.php' [Sat Aug 08 15:41:38.664966 2015] [rewrite:trace1] [pid 21776] mod_rewrite.c(475): [client 127.0.0.1:45382] 127.0.0.1 - - [engine.bbb.ru/sid#85a910][rid#dd7890/initial] [perdir /opt/lampp/htdocs/bbb/_engine/] internal redirect with /ind.php [INTERNAL REDIRECT] [Sat Aug 08 15:41:38.665040 2015] [rewrite:trace3] [pid 21776] mod_rewrite.c(475): [client 127.0.0.1:45382] 127.0.0.1 - - [engine.bbb.ru/sid#85a910][rid#dde8b8/initial/redir#1] [perdir /opt/lampp/htdocs/bbb/_engine/] strip per-dir prefix: /opt/lampp/htdocs/bbb/_engine/ind.php -> ind.php [Sat Aug 08 15:41:38.665044 2015] [rewrite:trace3] [pid 21776] mod_rewrite.c(475): [client 127.0.0.1:45382] 127.0.0.1 - - [engine.bbb.ru/sid#85a910][rid#dde8b8/initial/redir#1] [perdir /opt/lampp/htdocs/bbb/_engine/] applying pattern '^$' to uri 'ind.php' [Sat Aug 08 15:41:38.665046 2015] [rewrite:trace1] [pid 21776] mod_rewrite.c(475): [client 127.0.0.1:45382] 127.0.0.1 - - [engine.bbb.ru/sid#85a910][rid#dde8b8/initial/redir#1] [perdir /opt/lampp/htdocs/bbb/_engine/] pass through /opt/lampp/htdocs/bbb/_engine/ind.php 

Обратите внимание на то, что каждая строка помечена указанием уровня (rewrite:trace_). Видимо, если вы нашли в логе какую-то одну, особо нужную вам строку, и хотите посмотреть только однотипные, то меняете уровень трассировки, перезагружаете Apache и повторяете операцию. Мне лично кажется такой путь не совсем облегчающим задачу. Куда легче, на мой взгляд, сначала скопировать строки в отдельный файл, ориентируясь только по времени операции (по минутам). Потом отделить от них другие нужные строки путем удаления ненужной информации (search-replace). Я сначала даже думал сделать на PHP инструмент для просмотра логов такого рода. Но потом необходимость отпала сама собой (остановлюсь на этом ниже).

Отладка действует именно для того виртуального хоста, для которого указана

Если домен engine.bbb.ru использует внешние стили css, которые берутся с домена bbb.ru, и проблема именно в этом, то не надо включать отладку в пределах виртуального сервера engine.bbb.ru, а надо включать в виртуальном сервере bbb.ru. Тогда все вызовы к домену bbb.ru надо смотреть в логах ошибок (не доступа!) домена bbb.ru. При этом вызовов к трассируемым объектам не будет в логах доступа вообще!

А можно не пользоваться столь стрессовым RewriteEngine вообще?

Можно перейти на использование всего одного скрипта на весь сайт и делать весь рерайтинг в нем. На PHP это сделать легче, да и отлаживать куда проще. Кроме явных преимуществ в вопросах безопасности сайта, мы получаем удобство рерайтинга без нервотрепки. Для того, чтобы перейти на такую схему работы, наш .htaccess должен быть примерно такой:

RewriteEngine on  # правило перенаправления "с www" на "без www" RewriteCond %{HTTP_HOST} ^www.our-site.ru$ RewriteRule ^(.*)$ http://our-site.ru/$1 [R=301,L]  # всего 4 конкретных файла, которые проходят мимо правила. RewriteCond %{REQUEST_URI} !favicon.ico$ RewriteCond %{REQUEST_URI} !robots.txt$ RewriteCond %{REQUEST_URI} !sitemap.xml$ RewriteCond %{REQUEST_URI} !^/dispatch.php$ RewriteRule ^.*$ /dispatch.php [L] 

И в скрипте dispatch.php очень советую не забыть запретить прямой вызов самого dispatch.php.

<?php  if (preg_match('#^/dispatch.php#', $_SERVER['REQUEST_URI']) == 1) {  redirect_to_bad_uri(); } 

Если вам этот подход вдруг захочется перенять, то рекомендую скрипт dispatch.php назвать как-нибудь иначе. Я использовал это название только в целях наглядности.

К слову, этот подход внедряется довольно активно. Этому мы должны быть благодарны внедрению ЧПУ (урлов, понятных для человека, хотя лично для меня они очень непонятны). Практически во всех современных движках он уже действует.

habr.com


You May Also Like

About the Author: admind

Добавить комментарий

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

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.

Adblock
detector