Итак, возьмем .htaccess от Joomla! (я взял от версии 3.4.1) и посмотрим, что в нем интересного и как это все работает.
В первой незакомментированной строке видим команду IndexIgnore
IndexIgnore *
Если в конфигурации вашего сервера или в .htaccess файле включена опция
Options +Indexes
, то при обращении к папке, в которой нет файлов index.php или index.html, на экране браузера будет выведен листинг этой папки со всеми файлами и вложенными папками.
Команда IndexIgnore предназначена для исключения каких либо файлов из этого листинга, например команда
IndexIgnore .htaccess .ftpquota .DS_Store robots.txt
исключает из листинга файлы .htaccess, .ftpquota, .DS_Store и robots.txt .
Указанная в .htaccess от Joomla! команда
IndexIgnore *
исключает из листинга все файлы. Т.е. листинг будет, но он будет пустой.
Далее следует строка.
Options +FollowSymlinks
Эта строка предназначена для корректной работы перенаправления в некоторых конфигурациях серверов. Но если она уже установлена в конфигурации сервера, то ее повторное использование может привести к проблемам. Возможно, вам потребуется закомментировать ее, если после переименования дистрибутивного htaccess.txt в .htaccess ваш сайт перестанет работать.
Следующая строка
Options -Indexes
отключает вывод листинга при отсутствии в папке index-файла. Если вы все-таки предполагаете использовать вывод листинга какой либо папки, то вам придется более тонко настроить команду IndexIgnore, так как она имеет глобальное действие на все поддиректории. Например
IndexIgnore .htaccess *.php *.xml *.cgi *.js
Идем дальше. Начинается самое интересное — перенаправление.
RewriteEngine On
Команда включает механизм перенаправления в модуле mod_rewrite.c .
Далее следует блок строк решающий некоторые вопросы безопасности.
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR] RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR] RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR] RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) RewriteRule .* index.php [F]
Команды RewriteRule этого блока проверяют строку параметров запроса по следующему алгоритму:
- Строка параметров запроса закодирована в Base64
- Строка параметров запроса содержит тэг <script>. Флаг [NC] в конце второй строки указывает, что проверка выполняется без учета регистра.
- Строка параметров запроса содержит операцию установки php- переменной GLOBALS через url
- Строка параметров запроса содержит операцию установки php-переменной $_REQUEST через url
В случае выполнения одного из этих условий, выполняется правило
RewriteRule .* index.php [F]
Флаг [F] (от forbidden — запрещено) в этом правиле дает инструкцию серверу немедленно отправить ответ с кодом ошибки 403. При этом будет произведено перенаправление на главную страницу сайта index.php как указано в команде.
Далее начинается блок SEF-оптимизации.
Первая строка устанавливает переменную окружения HTTP_AUTHORIZATION переданными в запросе параметрами HTTP авторизации.
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Далее идут строки:
RewriteCond %{REQUEST_URI} !^/index\.php RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule .* index.php [L]
Рассмотрим по порядку. Первая строка проверяет отсутствие index.php в строке запроса.
RewriteCond %{REQUEST_URI} !^/index\.php
Следующая строка проверяет, что запрос не указывает на существующий файл.
RewriteCond %{REQUEST_FILENAME} !-f
Следующие строка проверяет, что запрос не указывает на существующую директорию.
RewriteCond %{REQUEST_FILENAME} !-d
Таким образом, благодаря этим строкам, правило не будет выполняться если в запросе указан существующий файл или директория.
В случае, если вышеперечисленные условия выполнены, отрабатывает правило в последней строке.
RewriteRule .* index.php [L]
Флаг [L] означает, что это последнее правило.
Это правило переадресовывает запрос к скрипту index.php . Т.е. не зависимо от того что у нас передано в url, если это не файл и не папка, будет выполнен скрипт index.php . При этом строка исходного запроса будет доступна скрипту через суперглобальный массив $_SERVER.
Например, запрос
http:/yoursite.com/news/2015/07/01?prm1=556
фактически выполнит
http:/yoursite.com/index.php
но в скрипте из $_SERVER мы можем получить следующее
$_SERVER['REQUEST_URI'] --> 'news/2015/07/01?prm1=556' $_SERVER['QUERY_STRING'] --> 'prm1=556'
Финиш.