Всё что нужно вашему .htaccess — набор необходимых правил

В сети можно найти достаточно много различных примеров с правилами реврайтов в .htaccess , добрая половина из которых содержит ошибки, множественные перенаправления(что отрицательно скажется на seo) и прочую гадость. Скажу по секрету: вторая половина вам тоже не нужна! Краткость — сестра таланта. Это аксиома.

Отойдём от этой аксиомы, для ввода в курс дела. Если пришел за правилами, гоу сразу вниз статьи.

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

Я бы рекомендовал таким писакам правил, командную строку + curl в зубы с параметрами отладки — заголовков и смотреть глазками, сколько переадресаций, каких, когда, куда, при каких обстоятельствах и т.п. А ещё удобнее для отладки, использовать менеджер запросов Postman, просто, красиво, всё на ладони:

Отладка htaccess правил

Откроем файл .htaccess любого wp движка, как известно wordpress поддерживает различные схемы формирования url на выбор.

<ifModule mod_headers.c>
    <FilesMatch ".(flv|gif|jpg|jpeg|png|ico|swf|js|css|pdf)$">
    Header set Cache-Control "max-age=2592000"
        </FilesMatch>
</IfModule>
# BEGIN WordPress
# Директивы (строки) между `BEGIN WordPress` и `END WordPress`
# созданы автоматически и подлежат изменению только через фильтры WordPress.
# Сделанные вручную изменения между этими маркерами будут перезаписаны.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

Мы увидим весьма лаконичные правила. Все идёт на index.php а дальше PHP логика рулит. Отделяем далее основной REQUEST_URI от параметров GET просто:

$request = strtok($_SERVER['REQUEST_URI'], '?');

Мухи отдельно, котлеты отдельно. И рулим уже кодом! Это правильно.

Поговорим о редиректах 301 убирающих/добавляющих слэши в конце(касается в общем-то любых редиректов)

RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule .* %1 [R=301,L]

На какой протокол apache вернет 301? Будучи на 80 порту он вернет редирект на http, а на 443 — https

Итак, у вас нет своего сертификата на сервере, он вам не нужен. Вы за flexible от cloudflare юзаете его https, при разработке вы протестили свои htaccess редиректы, на 80 порту apache у вас запущен, всё окей? Нет.Хотя работает и за клоудом. Но как? Через жопу:

  1. Получая запрос по протоколу https(443) на /request///// клоуд отправляет его на сервер в том же виде на протокол http(80)
  2. Получая запрос /request///// apache редиректит его на по своему 80 протоколу http://example.com/request/
  3. Получая запрос по протоколу http(80) на /request/ клоуд редиректит его на https (вы же поставили always use https?)
  4. Получая запрос по https на /request/ клоуд наконец отправляет его в том же виде на сервер по протоколу 80

Результат — 1 лишний редирект. А вот так правильно:

RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule .* https://%{SERVER_NAME}%1 [R=301,L]

Это же относится ко всем вариантам редиректов 301-302. И вот таких подводных камней может быть масса, особенно когда начинают извращаться, разбирая по слешам запросы в .htaccess, формируя кучу реврайтов, передавая из «разобранного» между слешей на GET параметры всякие категории, id по отдельности и т.п. Зачем? Юзай себе один реврайт всегда на index.php, из него разбирай запрос как удобно, GET параметры и подключай логику инклудами, php гибок и прост! Кроме того, если придется перебираться на nginx — меньше будет мороки с трансформированием в его правила.

Итак, пару золотых правил .htaccess

  • Без слешей в конце url
  • Со слешами в конце url

В обоих случаях двойные слеши будут удалены редиректом, а также будут удалены index.php/index.html в конце любого пути

Без слешей:

DirectoryIndex index.php
AddDefaultCharset UTF-8
Options -Indexes

<ifModule mod_headers.c>
    <FilesMatch ".(flv|gif|jpg|jpeg|png|ico|swf|js|css|pdf)$">
    Header set Cache-Control "max-age=2592000"
        </FilesMatch>
</IfModule>

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /

RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule .* https://%{SERVER_NAME}%1 [R=301,L]

RewriteCond %{THE_REQUEST} //
RewriteRule .* https://%{SERVER_NAME}/$0 [R=301,L]

RewriteCond %{REQUEST_URI} ^(.+)/index\.(php|html)
RewriteRule ^(.+)/index\.(php|html)([^/]*)$ https://%{SERVER_NAME}/$1 [R=301,L]

RewriteCond %{THE_REQUEST} /index\.(php|html)
RewriteRule ^index\.(php|html)([^/]*)$ https://%{SERVER_NAME}/ [R=301,L]

RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /index.php [L]
</IfModule>

И со слешами:

DirectoryIndex index.php
AddDefaultCharset UTF-8
Options -Indexes

<ifModule mod_headers.c>
    <FilesMatch ".(flv|gif|jpg|jpeg|png|ico|swf|js|css|pdf)$">
    Header set Cache-Control "max-age=2592000"
        </FilesMatch>
</IfModule>

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /

RewriteCond %{THE_REQUEST} //
RewriteRule .* https://%{SERVER_NAME}/$0 [R=301,L]

RewriteCond %{REQUEST_URI} ^(.+)/index\.(php|html)
RewriteRule ^(.+/)index\.(php|html)([^/]*)$ https://%{SERVER_NAME}/$1 [R=301,L]

RewriteCond %{THE_REQUEST} /index\.(php|html)
RewriteRule ^index\.(php|html)([^/]*)$ https://%{SERVER_NAME}/ [R=301,L]

RewriteCond %{REQUEST_URI} !(.*)/$
RewriteCond %{REQUEST_URI} !(\.html|\.txt|\.xml)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ https://%{SERVER_NAME}/$1/ [L,R=301]

RewriteRule ^index\.php$ - [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /index.php [L]
</IfModule>

 

 

Оставить ответ

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