универсальный .htaccess

Вашему вниманию мой вгляд на правила обработки URL с объяснениями и коментариями «почему так?»

Сперва логика

Объясню сперва логику:
1) все страницы имеют .html окончания.
2) все языки для страниц имеют вид pagename.en.html или pagename.html для языка по умолчанию. Никто, конечно, не запрещает иметь ссылки, где язык идёт вначале как /en/
3) «входной» скрипт только один в docroot.
4) Разрешены запросы на другие скрипты только в docroot
5) Соглашение по определению окончаний в url:
# site.com/
# site.com/index -> site.com/
# site.com -> site.com/
# site.com/file/ -> site.com/file.html
# site.com/file -> site.com/file.html
# site.com/dir/file ->site.com/dir/file.html
# site.com/dir/file/ -> site.com/dir/file.html


Но это можно менять.

Структура .htaccess

Теперь перейдём к самой структуре .htaccess. Замечу ещё, что будет работать только для апачей версий 2.x и старше.

Сперва полностью код:

 

Разбор полёта

Теперь, разберём построчно.

Сразу важный момент: выключена автоматическая подстановка слеша в конец и выключен MultiViews (с ним работать не будет).

Третья строчка проверяет на статические файлы — их пропускаем не меняя запрос. Возможно, стоило бы сделать проверку на наличие файла, но оставим это дело механизму 404. Последний |test\.php$ сделан для различных тестовых файлов, но на продакшене это дело надо убирать.

вариант без test

Самая важная часть — так как идёт преобразование расширений (далее по коду), то скрипт будет уходить всегда в подзапрос и может уйти в бесконечный цикл. Для того, чтобы этого не произошло, ловим начало подзапросов и отправляем на уже исправленный «входной» скрипт текущий запрос по URL. Это можно посмотреть включив rewrite_log в апаче.

Все попытки попасть на /index' или index.html’ будут перенаправлены на URL /'.

Решает одну из частей «соглашения»: убирает завершающие /’ из обращений к страницам. Правила описаны в пункте (5) вначале. В комментарии написано, что если хотим использовать внешний редирект (меняется url в строке браузера), то используем [R=301,L], если внутренний (не меняет url в строке браузера), то [R=301] или [L]

Решает ещё одну из частей «соглашения», что все запросы на страницы должны иметь окончание .html. Небольшими манипуляциями можно сделать наоборот.

Решает проблему пропущенного языка в строке запроса перенаправляя на страницу с языком по умолчанию.

Решает часть соглашения №4 — разрешает запросы к другим php/html файлам в папке %DOCUMENT_ROOT% сайта.

Если всё как надо, то направляем запрос на «входной» скрипт.

Разное

Что касается флагов апача: везде используется QSA (дополнять строку запроса) — об этом забывать нельзя, чтобы не терять параметры. E=NS:1 устанавливает переменную окружения NS равную 1 — нужна для определения подзапроса (подзапроса созданного правилами преобразования по «соглашению», а не каким-нибудь другим подзапросом).

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

Ваш адрес email не будет опубликован.