Привіт, друзі. Сьогодні хотілося б обговорити дуже заїжджену, але завжди актуальну тему – це 301 Редирект (Permanent Redirect 301) – seo-тусовці і без формальностей саме це мається на увазі під словом «редирект». Технічно це є відповідь сервера на звернення до нього, ця відповідь має код 301, позначає, що адресу звернення був змінений назавжди (moved permanently). У результаті всіх цих хитрих махінацій ми повинні отримати якийсь новий кінцевий адресу.

Я вважаю, що вам не потрібні ці технічні аспекти, а тому хочу поговорити про прикладні речі – коли і в яких ситуаціях краще використовувати редирект, яким чином і за допомогою яких команд можна налаштувати правила переадресування і т. д. А так само розглянемо інструменти і сервіси, за допомогою яких можна перевірити правильність редиректів.

Ще я хочу поділитися випадки з моєї практики, іноді трапляються такі, що навмисне не придумаєш. Саме тому важливо розглядати такі ситуації, адже можна ніколи і не дізнатися про існуючу проблему зі своїм сайтом, а вона буде заважати просуванню…

Так як пост вийшов дуже великим, то я вирішив зробити зміст для вашої зручності:

  • Редирект:
    • Коли потрібно робити?
    • Коли можна робити?
    • Коли не варто робити?
  • Дуже важливі рекомендації!
  • Практика редіректу:
    • Через .htaccess
    • Через PHP
    • Через nginx
  • Перевірка http-заголовків

Коли НЕОБХІДНО робити 301 редирект

В першу чергу редирект застосовується, коли сторінка (група сторінок або цілий розділ) змінила свою адресу — найчастіше це трапляється при зміні структури сайту, перейменування основообразующей частини до а або зміну принципу формування адрес (простіше кажучи, ЧПУ). На жаль, не всі про це замислюються, коли щось міняють на сайті, і в результаті виникає купа дублів, що призводить до втрати позицій або навіть накладення санкцій з боку пошукових систем. У своїй роботі я дуже часто стикаюся з такими ситуаціями, і це коштує багато нервів, щоб все виправити і нівелювати наслідки. Від себе можу порекомендувати перед будь-якою роботою по зміні типу ЧПУ або переробці структури скласти план поточної структури сайту, всіх його розділів і прикладів кінцевих сторінок. Все це необхідно буде перевірити після завершення робіт, щоб при переході за старою адресою ми потрапляли на новий, а сервер віддавав редирект з кодом 301 (а не 302).

Наступний частий випадок використання 301 редіректу – зміна адреси сайту або склейка дзеркал. Якщо ви вирішили поміняти адресу сайту у зв’язку з ребрендингом компанії або зареєстрували новий більш красивий і короткий домен для зазначення його на друкованій промо-продукції — дуже важливо, щоб при зверненні до адреси на старому домені користувач потрапляв на ту ж саму сторінку (а не на головну сторінку), але на новому домені. Що стосується промо-сайтів, то зазвичай вони складаються з однієї-двох сторінок, посилання з яких ведуть на основний сайт, або ж при переході на промо-сайт відразу відбувається редірект на спеціальну сторінку основного сайту. Ще іноді при створенні сайту реєструється відразу кілька доменів, наприклад, з-за неоднозначного написання імені компанії на латиниці. Щоб інтуїтивно набираючи адресу, користувач потрапив куди треба, і реєструються кілька доменів – дуже важливо, щоб з усіх «допоміжних» доменів відбувався 301 редирект на один основний адресу. Ні в якому разі не можна допустити, щоб за всіма адресами був доступний один і той же сайт.

І ще про дзеркалах – може статися так, що ваш сайт буде доступний за адресами http://www.site.ru, http://site.ru і https://site.ru (останнє рідко, але буває) – це всі класичні помилки, які не можна допускати, і в їх вирішенні як раз бере участь 301 редирект. Так само як і у випадку з різними адресами сайтів, необхідно визначитися з головним дзеркалом (з www або без www) і налаштувати перенаправлення на основне дзеркало. Звичайно, пошуковики не дурні і в таких ситуаціях часто самі справляються, а так само їм можна допомогти, зробивши правильні налаштування панелі вебмастера і в robots.txt (для Яндекса, директива Host). Але seo – справа тонка, і я б не став покладатися на удачу, а скористався перевіреним способом!

Іноді трапляється дуже неприємна ситуація, коли копія сайту виявляється доступною не тільки при введенні в адресному рядку назви домену, але і IP-адресу сервера. Така ситуація навряд чи може відбутися на віртуальному хостингу, а ось якщо у вас виділений сервер, то запросто. Це може бути причиною некоректної установки сервера – вирішити проблему допоможе відключення можливості доступу при зверненні до ip-адресою, але найкраще тут виручить 301-редирект на рівні веб-вервера (apache або nginx). Пару місяців тому в мене трапилася якраз така ситуація – у мене був виділений сервер, на якому висіла частина сайтів, але під один із сайтів я вирішив взяти ще один окремий сервер. Я переніс сайт, все працювало як годинник, і ось одного разу натикаюся у видачі Гугла на клон мого сайту – шок, паніка – виявилося, що це ip адреса мого нового сервера і, зрозуміло, на ньому живе мій сайт, а при зверненні сервер віддає відповідь 200 OK, і Google проіндексував його повністю. На попередньому сервері такої проблеми не було, там спочатку був налаштований 301-редирект з ip на домен, вказаний в якості основного для цього ip. Тепер я навчений гірким досвідом і завжди перевіряю такі речі – будьте в курсі і ви, не повторюйте помилок. Проблему вирішили шляхом додавання в конфіги веб-сервера nginx 301 редіректу на основний домен, приклад коду покажу в практичній частині посту нижче.

Ситуація подібна до попередньої – коли копія сайту знаходиться і доступна через службовий тестовий домен, наприклад, виду site.hosting.ru. Такі випадки в моїй практиці теж зустрічаються, і, на відміну від попереднього випадку, це властиво як раз для віртуального хостингу. Для чого таке існує? Наприклад, у вас ще не куплений домен або ви переносите сайт з одного хостингу на інший, а NS сервера для домену не змінили, або ще не оновилися запису DNS провайдера. В таких ситуаціях і роблять тестові адреси, де ви можете все налаштувати і встановити, перш ніж передавати адресу сайту на новий хостинг. І ось деякі хостери грішать тим, що не закривають доступ до таких технічних адресами і при цьому навіть не забороняють їх індексацію. Якщо у вас сталася ця неприємна ситуація, то варто спробувати прописати 301-редирект з технічного адреси на основний у файлі .htaccess.

Ну і, звичайно ж, 301 редирект дуже люблять застосовувати правильні сеошники для боротьби з різними дублями сторінок. Чому тільки правильні сеошники? Та тому, що неправильні хуй забили на сайт клієнта і, що цілком ймовірно, навіть не заходячи на сайт, стали закуповувати посилання – на жаль, це не рідкість. До мене періодично звертаються замовники, які хочуть перевірити добросовісність своїх підрядників/працівників, що відповідають за оптимізацію та просування сайту, наскільки якісно йде робота – замовляють seo аудит сайту – і поки ще жодного разу не було такого, щоб я не знайшов на сайтах помилок або недоробок. Так що, майте на увазі – я завжди радий вам допомогти. Повернемося ж до дублям – я вважаю, що замість того, щоб закривати дублі від індексації, необхідно робити редирект на основну адресу, а всякі rel=”canonical” це вже не так цікаво. Зрозуміло, існує маса випадків, коли дублі вимушені, і тоді без канонізації не обійтися, але якщо є можливість зробити редирект, обов’язково робіть його. Часті випадки дублів, які необхідно перевіряти завжди: адреси зі слешем на кінці і без, адреси з параметрами і мітками – як це вирішувати, я розповім нижче.

Коли МОЖНА робити 301 редирект

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

Redirect 301 можна використовувати в якості відповіді сервера замість помилки 404 Not Found – іншими словами, користувач, перейшовши по неправильній посиланням або на неіснуючу сторінку, не побачить повідомлення, мовляв, «Вибачте, такої сторінки більше немає», а буде переміщений на іншу існуючу сторінку. Це дуже спірний момент серед фахівців, а тому я свою думку нікому не нав’язую. Але я віддаю перевагу використовувати саме редирект замість 404 помилки, і тут існує кілька варіантів розвитку подій… Дивіться, є 2 категорії 404 помилки: перша – класична, коли сторінку дійсно видалили, друга – коли поява помилки пов’язано з кривими зовнішніми посиланнями. У першому випадку, напевно, не варто робити редирект, а залишити 404 помилку як вона є. А от у другому випадку варто потурбуватися перенаправленням на правильний url-адресу, якщо його можна відновити з битою посилання, або перенаправленням на головну сторінку (або категорії).

Коли НЕ СЛІД робити 301 редирект

Кілька слів про те, коли редирект може вам нашкодити, а тому його не варто використовувати в наступних ситуаціях.

Найголовніше, щоб не наробити помилок, не варто зв’язуватися з редиректами, якщо ви на 100% не впевнені в тому, що ви робите або в чомусь сумніваєтеся. Прийміть це як дружню пораду 🙂

Перманентний редирект не варто використовувати для тимчасових рішень, це очевидно з її назви – для тимчасового переміщення використовуйте 302 Moved Temporarily. При цьому не відбудеться склеювання сторінок та сторінки з перенаправленням можна буде у будь-який час відновити.

Якщо з вашим доменом трапилися проблеми, наприклад, фільтри, бан і т. п., і ви вирішили змінити адресу сайту (домен), то не варто робити 301 редирект зі старого домену на новий — в результаті ви «приклейте» до нового домену і всі проблеми сторого. Тобто в результаті нічого і не зміниться. Так, було якийсь час рішення виходу з під гугл-фільтра Пінгвін за допомогою повного 301-редіректу зі старого домену на новий. Дійсно всі позиції відновлювалися до рівня як до санкцій, і це здавалося панацеєю від злого Пінгвіна, але при черговому апдейте алгоритму ця особливість була врахована і новий домен так само потрапляв під фільтр, в результаті нічого не покращувалось після зміни домену. Якщо вже ви вирішили змінити домен, то можна спробувати перенести весь контент на новий домен, а на старому видалити його і повісити заглушку з повідомленням про переїзд, а ще краще почати все «з нуля».

Способів зробити редирект дуже багато – через htaccess, php, javascript, налаштування сервера і т. д. – так от не треба намагатися використовувати відразу всі методи одночасно, занадто велика ймовірність «розбіжностей» між різними способами і можна, наприклад, отримати нескінченну циклічну перенаправлення.

Важливі рекомендації при роботі з редиректами

Коли ви працюєте зі складною структурою сайту або переробляє великий портал, часто трапляються множинні редиректи або довгі ланцюжки. Це означає, що редирект відбувається не в один крок, а на два і більше – це погана ситуація і її треба по можливості уникати. При переході за посиланням пошуковий робот, отримавши кілька перенаправлень поспіль, може подумати, що його обманюють і припинити слідувати далі і взагалі перестати зважати посилання. Ось вам приклад з моєї практики, одного разу мені на аудит попався сайт з такою несподіваною ланцюжком:

http://site.ru/tax/term/30 ->
http://www.site.ru/tax/term/30 ->
http://www.site.ru/tax/term/30/ ->
http://www.site.hosting.ru/404.php ->
http://www.site.ru/404.php

А ще в підсумку сторінка http://www.site.ru/404.php, яка повинна віддавати 404 помилку, віддає відповідь 200 OK. Це навіть мені розірвала мозок, а уявіть, що подумав би пошуковий робот, потрапивши в таку карусель! Мало того, що в ланцюжку взяли участь три різних домену, так ще й сторінка помилки каже, що вона не помилка і її треба індексувати.

По можливості прагніть до відсутності редиректів всередині сайту – якщо зовнішні посилання на сайт виправити вже не можна і редирект неминучий, то внутрішні посилання треба намагатися виправляти. Може бути це і не позначиться на якості індексації і ранжируванні, але і не можна бути впевненим напевно, а тому краще уникати таких спірних ситуацій. У відстеженні внутрішніх редиректів і взагалі помилок всередині сайту вам допоможе чудова програма CompraseR.

Складаючи прищепила редиректів в .htaccess виключайте реальні адреси директорій і файлів на сервері і слідкуйте за вибіркою. Ситуація для сайту, який потрапив мені одного разу на аудит у боротьбі з дублями сторінок категорій зі слешем на кінці і без, вебмастер перестарався трохи і навпаки тільки посилила проблему. Мало того, що під правила перезапису потрапили і реальні файли js-скриптів і css-стилів з-за чого вони перестали коректно працювати, так ще й деякі сторінки отримали непотрібний слеш на кінці і з’явилися дублі. Друзі, ретельно стежте, щоб складені правила поширювалися тільки на ту групу адрес, з якою ви працюєте, і обмежуйте всі інші.

Для пошуку проблемних сторінок і їх адрес, від яких необхідно позбутися, використовуйте можливості панелей вебмайстра від Яндекс і Google. Для Яндекса Вебмайстер: Вибираємо сайт –> Індексування сайту –> Виключені сторінки. Для Google Webmaster: Вибираємо сайт –> Оптимізація –> Оптимізація HTML; А так же: Вибираємо сайт –> Конфігурація –> Параметри URL.

Особливості індексації та переіндексації редиректів в Яндекс і Google. Коли ви будете боротися з дублями і проблемними адресами, зрозуміло, ви будете чекати видалення помилок з панелей вебмастера, тут є деякі особливості. З Google все просто – налаштували редиректи, зміни проіндексує протягом 2 тижнів, за цей же час почнуть зникати помилки і з панелі вебмастера, зазвичай через місяць всі помилки пропадають. З Яндексом ж є тонкість, і полягає в наступному – після простановки редиректів можна чекати зникнення помилок панелі вічно, я чекав одного разу півроку, поки не написав підтримку, де мені повідомили, що крім редіректу необхідно додатково закрити проблемні сторінки robots.txt і тільки тоді вони пропадуть з панелі вебмастера.

Взагалі рекомендую прочитати офіційні мануали від пошуковиків по темі: Переадресація 301 від Google і Обробка перенаправлень (редиректів) від Яндекс.

Permanent Redirect 301 через .htaccess

Такий спосіб установки редиректів є самим популярним і простим. Хоча, зізнатися, далеко все не так просто, як здається, тому що я планую написати окремий пост про htaccess. З плюсів цього способу можна відзначити, що редирект спрацьовує на рівні сервера і до запуску обробки будь-яких скриптів сайту не несе додаткового навантаження.

У вас на сервері (в корені, там де головний index.php) вже напевно є файл .htaccess. Якщо цей файл не видно:

  • Перевірте налаштування ftp-менеджера, він може приховувати системыне файли, яким і є файл htaccess
  • Зайдіть в файловий менеджер через панель управління хостера і перевірте права для файлу. Я маю на увазі не CHMOD, а групу і, наприклад, там може стояти користувач root, а ви підключаєтеся через ftp використовуючи доступ користувача власника домену.
  • Банально файлу може не бути 🙂 Тоді його слід створити, але під windows іноді виникає проблема, оскільки по суті файл .htaccess бачиться системою як файл без імені і тільки з розширенням. Пропоную простий спосіб – створюємо звичайний txt-файл, додаємо в нього рядок «RewriteEngine On» (без лапок), завантажуємо txt-файл на сервер, на сервері перейменовуємо файл .htaccess

Більшість правок, пов’язаних з перенаправленням слід писати на самому початку файлу після рядка «RewriteEngine On», щоб ці правила оброблялися в першу чергу. Важливо дотримуватися послідовності дій, т. к. команди обробляється сервером порядково з самого початку і до першого входження. Інакше кажучи, треба завжди починати з приватною і закінчувати більш загальною вибіркою.

Давайте розглянемо кілька найбільш поширених і корисних прикладів:

Редирект для домену www.site.ru на site.ru

RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

Редирект для домену site.ru на www.site.ru

RewriteCond %{HTTP_HOST} !^www\.(.*) [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]

RewriteCond %{HTTP_HOST} !^www\.(.*) [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]

Вищеописані варіанти редіректу відмінно працюють і не вимагають ніяких правок з вашої сторони — тільки вставити .htaccess файл. Однак для 100% надійності я б порадив вам інший варіант:

RewriteCond %{HTTP_HOST} !^www.site.ru$ [NC]
RewriteRule ^(.*)$ http://www.site.ru/$1 [R=301,L]

RewriteCond %{HTTP_HOST} !^www.site.ru$ [NC]
RewriteRule ^(.*)$ http://www.site.ru/$1 [R=301,L]

Або

RewriteCond %{HTTP_HOST} !^site.ru$ [NC]
RewriteRule ^(.*)$ http://site.ru/$1 [R=301,L]

RewriteCond %{HTTP_HOST} !^site.ru$ [NC]
RewriteRule ^(.*)$ http://site.ru/$1 [R=301,L]

Перший для тих, у кого основний домен з www, другий – у кого без www. Відповідно в обох прикладах треба замість «site» вписати назву вашого домену.
Отже, чим же дані варіанти краще? Дуже просто, вони перевіряють не тільки відсутність/наявність www в імені домену, але перевіряють і ім’я домену на повне його відповідність.
Живий приклад: Напевно ви стикалися з тим, що несподівано сайт може проиндексироваться по службовій адресою на хостингу (такий адресу видається, щоб до сайту можна було звернутися до прив’язки вашого реального домену), якому-небудь дзеркалу або взагалі ip-адресою! Так ось універсальні правила будуть лише верифікувати відсутність/наявність www, при цьому все одно, до якого домену звертається користувач або пошуковий робот.
Так ось скориставшись просунутим варіантом, ви на 146% будете впевнені, що ваш сайт буде доступний тільки і виключно за указному особисто вами доменному імені і з урахуванням www. Я користуюся тільки таким варіантом і вам рекомендую!

Редирект з http https

У світлі масового переходу сайтів на захищений протокол, необхідно знати, як зробити редирект з http https. До речі, якщо ви ще не обрали SSL-сертифікат, вам варто прочитати мій пост про SSL сертифікат для сайту — для чого він потрібен і де його взяти.

Нижче я пропоную вам декілька варіантів редіректу з протоколу http, https, які можуть працювати або не працювати в залежності від конфігурації саме вашого сервера, але якийсь із правил вам точно підійде:

RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

RewriteCond %{ENV:HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteCond %{ENV:HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteCond %{HTTP:X-HTTPS} !1
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

RewriteCond %{HTTP:X-HTTPS} !1
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

RewriteCond %{HTTP:CF-Visitor} ‘”scheme”:”http”‘
RewriteRule ^(.*)$ https://site.ru/$1 [R=301,L] #site.ru треба замінити на ваш домен

RewriteCond %{HTTP:CF-Visitor} ‘”scheme”:”http”‘
RewriteRule ^(.*)$ https://site.ru/$1 [R=301,L] #site.ru треба замінити на ваш домен

RewriteCond %{HTTP:X-Forwarded-Protocol} !=https
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

RewriteCond %{HTTP:X-Forwarded-Protocol} !=https
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

Якщо виникає циклічний редирект, то скористайтеся цим варіантом:

RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Редірект з протоколу https http (чесно, не знаю, навіщо вам це може знадобитися):

RewriteCond %{HTTPS} =on
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [R=301,L]

RewriteCond %{HTTPS} =on
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [R=301,L]

Внесу деяку ясність в незрозумілу абракадабру:

  • RewriteCond позначаємо умова, при збігу з яким буде виконано правило RewriteRule. За допомогою регулярних виразів задаються шаблони рядків.
  • Змінні сервера:
    • %{REQUEST_URI} — частина урла без доменного імені і GET-параметрів, наприклад, для сторінки, яку ви зараз читаєте: blog/post/4393,
    • %{HTTP_HOST} — хост або доменне ім’я, наприклад: alaev.info
    • %{QUERY_STRING} — рядок з набором GET параметрів, тобто частина урла після знака питання (і до решітки якоря, якщо він є).
    • %{REQUEST_FILENAME} — повний шлях у файловій системі сервера до файлу або скрипту відповідним цим запитом. Щоб було зрозуміло, адреса скрипта, як нам це звично такий — alaev.info/index.php а ось у файловій системі сервера це страшна рядок /var/www/alaev_info/data/www/alaev.info/index.php.
      Буває, роблячи редирект, ви отримуєте несподіваний результат, наприклад, хотіли в адресі http://site.ru/page-name?post=17434801_4060 прибрати параметри post=17434801_4060, вказали відповідні правила (про них буде написано нижче), а в результаті отримали рядок http://site.ru/usr/local/www/site.ru/www/page-name — від параметрів позбулися, але отримали дивний адресу. Це все тому, що ви не вказали на початку файлу після RewriteEngine On директиву RewriteBase /, яка встановлює конкретний, базовий URL для перетворень у контексті каталогу.
  • Метасимволи використовуються для завдання груп символів або «міток» в шаблоні:
    • ^ — мітка початку рядка,
    • $ — мітка кінця рядка,
    • ! – заперечення,
    • \ — екрануючий слеш, дозволяє вважати наступний за ним метасимвол звичайним символом,
    • . – точка, що позначає будь-який символ, але тільки один,
    • () – угруповання.
  • Модифікатори ставляться після звичайних символів, метасимволів або їх груп і розширюють можливості використання шаблонів:
    • ? — символ повторюється 0 або 1 раз,
    • * — Повторюється від 0 до 65536 раз,
    • + — Повторюється від 1 до 65536 раз.
  • Прапори визначають додаткові опції для даного правила і перераховуються в квадратних дужках через кому:
    • NC — (nocase) відключає перевірку регістру символів.
    • R — (redirect) зупиняє процес перетворення і повертає результат браузеру клієнта як редирект на дану сторінку (302, MOVED TEMPORARY). З цим прапором можна вказати інший код результату, наприклад R=301 поверне редирект з кодом 301 (MOVED PERMANENTLY). Як ви розумієте, це те саме, що нам і треба.
    • L — (last) зупиняє процес перетворення, і поточна посилання вважається остаточною.

Найпопулярніший випадок — редирект з index.php (html) на головну сторінку. На 90% сайтів зустрічається проблема дублювання головної сторінки за адресами http://site.ru і http://site.ru/index.php (або index.html, index.htm або будь-який інший варіант, не принципово, а то і все відразу). Де-то це явно, коли, наприклад, посилання з логотипу веде на site.ru посилання, а в меню веде на site.ru/index.php, де-то не явно, коли дубль знаходиться при введенні адреси index.php вручну. Важливо просто вирішити проблему. І я пропоную універсальний варіант, ось він:

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.(php|html|htm)\ HTTP/
RewriteRule ^(.*)index\.(php|html|htm)$ $1 [R=301,L]

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.(php|html|htm)\ HTTP/
RewriteRule ^(.*)index\.(php|html|htm)$ $1 [R=301,L]

Просто вставте цей код без змін після рядка після рядка «RewriteEngine On» і немає проблем!

Багато, хто починає боротися з дублями на сайті, задаються питанням, а звідки беруться такі ось посилання, які дублюють основну сторінку http://site.ru/page-name.html&post=-1234567_8901? Звідки взялася приставка &post=-1234567_8901 – це «добро» береться з вконтакте, коли хтось ділиться посиланням на ваш сайт у себе на стіні, у групі або паблике, то автоматично додається подібна рядок, мабуть, для відстеження якийсь статистики.

Щоб позбавитися від цієї нісенітниці раз і назавжди необхідно додати в htaccess:

RewriteCond %{REQUEST_URI} ^(.*)\&post=
RewriteRule ^(.*)\&post=(.*)$ $1 [R=301,L]

RewriteCond %{REQUEST_URI} ^(.*)\&post=
RewriteRule ^(.*)\&post=(.*)$ $1 [R=301,L]

Щоб вам був зрозумілий принцип, я наведу ще один приклад, його якраз запропонували вирішити в коментарях. Іноді ви можете виявити у себе ось такі посилання:
http://site.ru/&sa=U&ei=AsguT72dLdHLtAaZ0tyVDQ&ved=0CCwQFjAIOFo&usg=AFQjCNFwbE9i0bqrQUGJLoDh6xyVd1nhxg
Що сумно — ці посилання індексуються Гуглом і потрапляють в видачу.

Але не про це мова, я просто хочу, щоб ви зрозуміли механізм 301-редиректа в подібних випадках, а не задавали мені питання в коментарях по кожному випадку. А рішення буде таким:

RewriteCond %{REQUEST_URI} ^(.*)\&sa=
RewriteRule ^(.*)\&sa=(.*)$ $1 [R=301,L]

RewriteCond %{REQUEST_URI} ^(.*)\&sa=
RewriteRule ^(.*)\&sa=(.*)$ $1 [R=301,L]

Як бачите, ніякої різниці між цим і попереднім випадком ні, нехай у вас в до е буде &post= або &sa= або що завгодно — рішення однакове, просто треба замінити очевидні частини коду. Зрозуміло ж, правда?

Позбавляємося від параметрів або міток в адресі

Питання ставилося і в коментарях і багато разів на форумі, тому не можна його обійти стороною. Що робити з такими дублями: http://site.ru/?abrakadabra або більш реальний випадок http://site.ru?utm_source=twitterfeed&utm_medium=twitter

Цей випадок трохи відрізняється від наступного пункту, де ми будемо позбавлятися від параметрів для php-скрипта, так як тут звичайний адресу і параметри скрипт ми не передаємо. Ось рішення:

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

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

Як ви розумієте, значення «utm_source=» можна замінити на вашу «abrakadabra» і так жу буде відбуватися 301-редирект на адресу без всякої абракадабри.

Приклад позбавлення від параметрів скрипта в url сторінки

Нехай ми хочемо в адресі http://site.ru/index.php?lang=ru позбутися від параметра lang=ru так, щоб на виході отримати http://site.ru/index.php.

В .htaccess необхідно прописати такі рядки:

RewriteCond %{QUERY_STRING} ^lang=ru$
RewriteRule ^(.*)\.php\?(.*)$ $1\.PHP [R=301,NC,L]

RewriteCond %{QUERY_STRING} ^lang=ru$
RewriteRule ^(.*)\.php\?(.*)$ $1\.PHP [R=301,NC,L]

%{QUERY_STRING} — це рядок з набором змінних PHP, частина урла після знака питання (і до решітки якоря, якщо він є).

Викликаємо url — http://site.ru/index.php?lang=ru

RewriteCond %{QUERY_STRING} ^lang=ru$
Запитуваний url потрапляє під це правило, інших правил немає, тому буде виконаний RewriteRule рядком нижче.
RewriteRule ^(.*)\.php\?(.*)$ $1\.PHP [R=301,NC,L]

Вихідний url: http://site.ru/index.php?lang=ru
Шаблон розбирання до а: ^(.*)\.php\?(.*)$
URL буде розібраний по змінним: $1 = http://site.ru/index, $2 = lang=ru і зібраний назад вже у вигляді http://site.ru/index.php ($1\.php)
А далі буде 301 редирект на новий url.

Приклад правил при зміні структури сайту

RewriteRule ^post/category/(.*)$ blog/category/$1 [R=301,L]
RewriteRule ^post/(.*)$ blog/post/$1 [R=301,L]

RewriteRule ^post/category/(.*)$ blog/category/$1 [R=301,L]
RewriteRule ^post/(.*)$ blog/post/$1 [R=301,L]

Ось такі рядки мені довелося додати в htaccess файл, коли я змінив структуру свого блогу.

Раніше у мене були такі адреси: http://alaev.info/post/4358 і http://alaev.info/post/category/seo, що як-то ламало логіку в структурі – адже блог це тільки частина сайту, але чомусь пости належать сайту, а не блогу, а категорії належать постам, що теж зовсім нелогічно. Я вирішив відновити логіку, і вийшло: http://alaev.info/blog/post/4358 і http://alaev.info/blog/category/seo — тепер блог як окремий розділ сайту, а пости належать йому, і категорії належать блогу, а не постам.

З цього прикладу видно, що важливо дотримуватися послідовність правил. Якщо б я поміняв рядки місцями, тобто попереду йшла рядок RewriteRule ^post/(.*)$ blog/post/$1 [R=301,L] то редирект з адреси http://alaev.info/post/category/seo йшов на сторінку http://alaev.info/blog/post/category/seo а не як треба на http://alaev.info/blog/category/seo.

І останній приклад — розбір частою помилки з адресою від кореня сервера

Наприклад, ви вирішили виправити таку проблему, коли сторінка категорії доступна за двома адресами http://site.ru/razdel/podrazdel/index.php і http://site.ru/razdel/podrazdel/. Другий url є правильним і основним, а з url index.php на кінці є повним дублем, від якого необхідно позбутися.

Для того щоб зробити редирект з index.php на категорію ви прописуєте правило:

RewriteRule ^(.*)index\.php$ $1 [R=301,L]

RewriteRule ^(.*)index\.php$ $1 [R=301,L]

А в підсумку при зверненні до сторінки: http://site.ru/razdel/podrazdel/index.php
Редиректит на щось подібне: http://site.ru/home/site.ru/public_html/razdel/podrazdel/

Тобто чомусь виводить повний шлях від кореня сервера.

Для вирішення цієї проблеми (і не тільки цієї, до речі) необхідно, щоб на початку .htaccess файл стояла не просто рядок RewriteEngine On, але після неї йшла ще одна, яка обрізає повний шлях від кореня сервера) до кореня сайту, ось так:

RewriteEngine On
RewriteBase /

RewriteEngine On
RewriteBase /

Простий редирект сторінки на нову адресу

Самий простий випадок, коли треба зробити редирект однієї сторінки на іншу адресу. Якщо ж вам треба зробити редирект для декількох сторінок, то доведеться писати кілька правил, але в цьому випадку краще скористатися шаблонами, описаними вище. Є кілька абсолютно ідентичних варіантів синтаксису:

Redirect 301 /page-name1.html http://site.ru/page-name2.html
Redirect permanent /page-name1.html http://site.ru/page-name2.html
RedirectPermanent /page-name1.html http://site.ru/page-name2.html

Redirect 301 /page-name1.html http://site.ru/page-name2.html
Redirect permanent /page-name1.html http://site.ru/page-name2.html
RedirectPermanent /page-name1.html http://site.ru/page-name2.html

Вибирайте один з трьох, а особисто я віддаю перевагу перший варіант — він коротше, простіше і зрозуміліше. До речі, тут site.ru може бути не обов’язково тим же самим доменом, але будь-яким іншим.

На цьому закінчимо .htaccess і перейдемо до PHP.

Permanent Redirect 301 з допомогою PHP

Зазвичай PHP редирект я використовую, коли виникають труднощі з .htaccess або виявляється так, що функція на php виявляється більш логічною і зрозумілою.

Сам синтаксис 301 редіректу на php виглядає наступним чином:

header(“HTTP/1.1 301 Moved Permanently”);
header(“Location: http://site.ru”);
die(“Redirect”);

header(“HTTP/1.1 301 Moved Permanently”);
header(“Location: http://site.ru”);
die(“Redirect”);

Ці рядки повідомляють браузеру клієнта, що з якоюсь запитаної сторінки необхідно зробити перманентний редирект на адресу http://site.ru. При цьому http://site.ru може бути не тільки адресою головної сторінки сайту, але може бути і будь-яким іншим сайтом. Якщо ж щось пішло не так і сталася помилка, то в браузері ми побачимо напис «Redirect».

Щоб було зрозуміліше, наведу кілька прикладів функцій, які я написав для свого блогу alaev.info намагаючись вирішити певні завдання.

Функція, що дозволяє прибрати певний шматок з url

if (strpos($_SERVER[‘REQUEST_URI’], ‘http://alaev.info’) !== false) {
$real_page_url = “http://alaev.info”.str_replace ( “/http://alaev.info”, “”, $_SERVER[‘REQUEST_URI’] );
header(“HTTP/1.1 301 Moved Permanently”);
header(“Location: $real_page_url”);
die(“Redirect”);
}

if (strpos($_SERVER[‘REQUEST_URI’], ‘http://alaev.info’) !== false) {
$real_page_url = “http://alaev.info”.str_replace ( “/http://alaev.info”, “”, $_SERVER[‘REQUEST_URI’] );
header(“HTTP/1.1 301 Moved Permanently”);
header(“Location: $real_page_url”);
die(“Redirect”);
}

Одного разу у мене виникла проблема, що в панелі вебмастера вилізла купа помилок 404, адреси цих сторінок були виду http://alaev.info/http://alaev.info/post/4358, тобто звідки-то в адресі з’явився дублюючий адресу сайту. І тоді я написав функцію, яка перевіряє, чи є в URI (зауважте, не посилання, а URI) входження «http://alaev.info» і якщо є, то вирізаємо з адреси цей шматок і записуємо результат в змінну $real_page_url, а потім робимо 301-редирект на вірний адресу змінної.

Функція, що прибирає кінцевий слеш з url

if ( ( $_SERVER[‘REQUEST_URI’], – 1, 1 ) == ‘/’ ) {
$requested_url = rtrim($requested_url, ‘/’);
header(“HTTP/1.0 301 Moved Permanently”);
header(“Location: $requested_url”);
die(“Redirect”);
}

if ( ( $_SERVER[‘REQUEST_URI’], – 1, 1 ) == ‘/’ ) {
$requested_url = rtrim($requested_url, ‘/’);
header(“HTTP/1.0 301 Moved Permanently”);
header(“Location: $requested_url”);
die(“Redirect”);
}

Ось така найпростіша функція, яка дивиться, чи є в шукане адерсе сторінки слеш на кінці, і якщо він є, то слеш обрізається і відбувається 301-редирет на адресу без слеша.

Існує ще маса варіантів, що дозволяють віддавати команду перенаправлення на різних мовах програмування, типу ASP, Ruby on Rail і т. д., але я з цими мовами не знайомий, тому не буду тут мудрувати і пудрити мізки вам. Ще можливі редиректи за допомогою метатега meta refresh, а так само перенаправлення на javascript – але це доля нечистих на руку дорвейщиков, а пошуковики ці редиректи не розуміють, вони отримую відповідь від сервера 200 OK. Так що ці варіанти ми не розглядаємо.

Permanent Redirect 301 для сервера nginx

Пам’ятаєте я писав про дзеркало мого сайту, доступного за ip? У підсумку проблему вирішили редиректом, прописаним в конфігураційному файлі сервера, зазвичай він розташований тут /etc/nginx/nginx2.conf. Там прописали ось такі рядки:

server {
listen 1.2.34.123:80 default;
server_name _;
rewrite ^/(.*)$ http://site.ru/$1 permanent;
}

server {
listen 1.2.34.123:80 default;
server_name _;
rewrite ^/(.*)$ http://site.ru/$1 permanent;
}

Тут йдеться про те, що якщо йде звернення до ip-адресою через 80-й порт, то необхідно робити permanent redirect на site.ru.

Однак техпідтримка не рекомендувала мені так чинити зі словами: «Більш коректно буде налаштувати HTTP-сервер таким чином, щоб він просто закривав з’єднання, якщо до нього звертаються за адресою, який не вказаний явно в конфігурації HTTP-сервера, це найбільш надійний, простий, безпечний і найменш вимогливий до ресурсів сервера варіант. Через деякий час сторінки, які будуть недоступні, швидше за все, будуть викинуті з індексу пошукових систем.»

Наступний рада був такий: «Коли потрібно буде просто закривати з’єднання замість перенаправлення, то вкажіть замість рядка ‘rewrite ^/(.*)$ http://site.ru/$1 permanent;’ такий рядок ‘return 444;’. Потім виконайте: ‘invoke-rc.d nginx reload’».

Раптом це комусь допоможе.

Приклади редиректів в найпоширеніших випадках

Редирект для домену www.site.ru на site.ru

server {
listen 80;
server_name www.site.ru;
rewrite ^ http://site.ru$request_uri? permanent;
}

server {
listen 80;
server_name www.site.ru;
rewrite ^ http://site.ru$request_uri? permanent;
}

Редирект для домену site.ru на www.site.ru

server {
listen 80;
server_name site.ru;
rewrite ^ http://www.site.ru$request_uri? permanent;
}

server {
listen 80;
server_name site.ru;
rewrite ^ http://www.site.ru$request_uri? permanent;
}

Редірект з адреси http://site.ru/index.php на http://site.ru/

location = /index.php {
if ($request_uri = /index.php) {
rewrite ^ http://$host? permanent;#redirect 301
}
fastcgi_pass unix:/tmp/fastcgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

location = /index.php {
if ($request_uri = /index.php) {
rewrite ^ http://$host? permanent;#redirect 301
}
fastcgi_pass unix:/tmp/fastcgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

Ось як-то так. Я в налаштуваннях конфіги для nginx не сильний, завжди обходжуся налаштуваннями апача, так що, якщо у вас з’явилися якісь питання по nginx, то я навряд чи зможу вам допомогти…

Як перевірити HTTP заголовки і статуси відповіді сервера

Я хотів у цьому розділі описати різні сервіси та плагіни для перевірки відповіді сервера, але розумію, що цей пост вже настільки великою за обсягом, що доведеться обмежитися просто посиланнями на розширення для браузерів Chrome і Firefox.

Додаток HttpFox для Firefox

HttpFox (ось посилання на аддон) — це мій улюблений інструмент відстеження http-заголовків. HttpFox порядково показує хід завантаження сторінки, що дозволяє відстежувати, наприклад, ланцюжки редиректів і взагалі порядок і швидкість завантаження сторінки. Якщо ви користуєтеся Мозиллой, то однозначно рекомендую.

Розширення HTTP Headers для Chrome

Сам я не користуюся розширенням HTTP Headers (ось посилання на нього), але інтернети мені порадили звернути увагу саме на нього. Якщо у вас є варіанти трохи краще, будь ласка, відпишіть в коментарях.

На цьому я завершую свій страшенно довгий і нудний пост, друзі.
Спасибі, що дочитали до кінця, я сподіваюся, він виявився для вас реально корисним.
Коментуйте, задавайте питання, розповідайте про своїх цікавих ситуаціях. До зв’язку!

З повагою, Олександр Алаєв