С недавних пор, заходя в Google Webmaster Tools, заметил у себя на сайте рост количества ошибок типа «Переход не выполнен», которые в моём случае возникали из-за так называемой циклической переадресации. Таковы уж особенности используемого «движка» сайта. Но ни в одном из браузеров данная ошибка не повторялась, при запросе «руками», то есть посредством telnet — тоже никаких аномалий замечено не было. Тем не менее, ошибки в GWT продолжали появляться вновь и вновь, указывая на те же самые URL'ы моего сайта и раздражая одним лишь своим существованием. Пришлось здорово поломать голову, но докопаться до сути проблемы всё же удалось.
Итак, на сайте есть облако тэгов, генерирующее ссылки вида: /blog/tag/название_тэга/. Поскольку тэги задаются пользователями, то могут содержать практически любой UTF-8 символ. Кроме того, на такие страницы (с топиками по определённому тэгу) периодически ставят ссылки с других сайтов/соцсетей/форумов. Часто, из-за различий в способах кодирования URL'ов эти ссылки ведут на страницы, не являющиеся каноническими.
Приведу пример. Есть тэг «гарри поттер», который в закодированном виде может быть как «гарри+поттер», так и «гарри%20поттер». На сайт могут стоять ссылки с обоими вариантами. Но для движка сайта, при раскодированни REQUEST_URI эти ссылки абсолютно идентичны, из-за чего возникают дубли страниц, чего поисковые системы очень не любят. Для борьбы с этими дублями при загрузке страницы я раскодирую URL, а потом кодирую его обратно при помощи PHP-функции urlencode() и сравниваю с первоначально запрошенной строкой. Если они не совпадают — отдаём браузеру 301-й код и отправляем его на правильный URL. Таким образом, дубли страниц в глазах поисковой системы «склеиваются».
Вроде бы всё довольно просто. Отчего же Googlebot стал зацикливаться на некоторых из подобных ссылок? На счастье, в GWT есть специальная функция — «Просмотреть как Googlebot», которая позволяет взглянуть на сайт как бы глазами поискового бота. Ну что же, пробуем. Для данного примера я возьму другой тэг: «guns'n'roses». Итак, указываем боту загрузить страницу /blog/tag/guns'n'roses/. Бот нам отвечает, что всё хорошо, получен ответ:
HTTP/1.1 301 Moved Permanently
...
Location: /blog/tag/guns%27n%27roses/
Всё правильно, одиночные кавычки согласно RFC 3986 кодируется как %27. Ок, теперь пробуем направить бота на URL /blog/tag/guns%27n%27roses/ (как если бы мы были обычным браузером). В ответ получаем:
HTTP/1.1 301 Moved Permanently
...
Location: /blog/tag/guns%27n%27roses/
и совершенно справедливое на первый взгляд замечание: «На странице обнаружена переадресация на саму себя. Это может привести к бесконечному циклу переадресации.»
Но в логах сервера видим, что на самом-то деле запрос снова был: «GET /blog/tag/guns'n'roses/ HTTP/1.1» вместо ясно и чётко указанного «GET /blog/tag/guns%27n%27roses/ HTTP/1.1». Выходит, Googlebot решил по-своему интерпретировать значение директивы Location, наплевав на RFC, замучав бессмысленными запросами себя и мой сайт.
Дальнейшее гугление помогло выяснить, что поисковый бот Гугла питает особую симпатию к следующим символам:
, @ ~ * ( ) ! $ '
и не преобразует их к соответствующим кодам
%2C %40 %7E %2A %28 %29 %21 %24 %27
чем может здорово подпортить нервы и потратить время и без того замученных вебмастеров :)
Автор: Robin_Bad