Не обрабатывается заголовок запроса if modified since. Заголовок Last-Modified, Symfony и ускорение поисковой индексации. Как заголовок Last-Modified ускоряет поисковую индексацию

Every day Yandex indexes millions of pages and adds them to the search database. To avoid filling it with documents that will never show up in the search results, Yandex analyzes each document using a special algorithm.

If the algorithm determines that the page is unlikely to become one of the most relevant answers for any search, the page isn"t included in the current search database.

Thus, not all the indexed documents can be seen in the Yandex search results. The removal of the page from the search database doesn"t affect the page or the site traffic, because this page wouldn"t appear in the search anyway.

In addition, Yandex continues reindexing and analyzing these documents in the same way as others. If at some point the algorithm reveals that the page can get into the search results, it will be added to the search engine database.

What is a page duplicate?

Page duplicates are site pages that have identical content but different URLs.

  • http://example.com and http://example.com/index.php/ ,
  • http://example.com/page/ and http://example.com/page .

If both pages are indexed by the Yandex robot, the indexing system groups them as duplicates. Only one of the pages is listed in the search results.

There are many reasons why duplicate pages may come up:

  • Natural reasons (for example, if a page with a product description is available in several categories of an online store).
  • Issues related to incorrect site structure.

To have the right page in the search results, we recommend that you indicate it for the Yandex robot. Here"s how you can do it:

  • Set up a 301 redirect from one duplicate page to another. In this case the search will register the target of the redirect.
  • Specify the preferred (canonical) URL for the page to be included in the search.

My site has moved (the URL changed). What should we do?

If the old and new site pages are exactly the same, the server should respond with a 301 error (“Moved Permanently” ) when the old page is requested . The Location field should contain the new site"s URL. If the old site has been shut down, you can speed up its removal from the index by filling in this form: Remove URL .

You overloaded my server. Please stop.

You are trying to download confidential information from our server. What should we do?

The robot takes links from other pages. This means that that some other page contains links to confidential sections of your site. You can either protect them with a password or disallow indexing by the Yandex robot in the robots.txt file. In both cases, the robot won"t download confidential information.

How do I protect myself from the fake robots that pretend to be the Yandex robots?

Your robot tries to download my site pages using broken links. Why?

The robot takes links from other pages, which means that one of them contains broken links to your site. Perhaps you changed the site structure and the links on other sites became broken.

What does the robot do if there"s a redirect on the page? What if I use the refresh directive?

When the Yandex robot receives a respond with the 3xx code heading (which means the URL is a redirect), it adds the redirect"s target URL to its crawling list. If it is a constant redirect (301 code or the page contains a refresh directive), the old URL is excluded from the crawling list.

My page is regularly missing from the search results. What"s the problem?

If the robot gets an error when contacting a page (for example, due to unstable hosting), it removes the page from the search until the next successful contact.

Can I manage reindexing frequency with the Revisit-After directive?

No. The Yandex robot ignores it.

Which data transfer protocols are supported for indexing?

Right now, Yandex supports two protocols: HTTP and HTTPS.

How do I tell the robot that it should index pages with or without a forward slash ("/") at the end of the URL?

For the Yandex robot, pages with a “/” at the end of the URL are different from those without it. If the pages are identical, set up a 301 redirect from one page to the other (you can set it in the htaccess file) or indicate the

В области поисковой оптимизации сайтов (SEO) гуляет вообще очень много разных мифов. Какие-то из них имеют под собой основу, какие вообще взялись не пойми откуда. В этой заметке рассмотрим один из них — использование заголовка ответа last-Modified.

Некоторое время назад к нам попал некий документ, озаглавленный «Рекомендации Ingate для веб студий по продвигаемым сайтам». И одна из «рекомендаций» была следующей:

После редизайна или на новом разрабатываемом сайте должна быть прописана дата последней модификации страниц сайта (Last Modified)

Для добавления на сайт на PHP информации о дате последней модификации страниц необходимо в самое начало исходного кода каждой страницы вставить скрипт

header ("Last-Modified: " . date("D, d M Y H:i:s", time()) . " GMT");
?>

Именно эта дикая ахинея, эта несусветная чушь и откровенно бредовый код и сподвигли меня написать эту заметку. Здесь я постараюсь объяснить, что такое Last-Modified, зачем он нужен и как его используют браузеры и поисковые машины.

Что такое Last-Modified

Веб-сервер при передаче информации клиенту (браузеры или поисковому роботу) сообщает довольно много дополнительных данных. Их можно посмотреть в консоли браузера, например:

настройте сервер на выдачу корректных заголовков ответов (например, если страница не существует, выдавать ошибку 404, а если поступил запрос If-Modified-Since, то выдавать код 304, если страница с указанной в запросе даты не изменялась).

Также можно увидеть, что если сервер никак не реагирует на условный запрос GET, то он ничем не отличается от обычного запроса. То есть, заголовок Last-Modified с текущим временем, к тому же и неправильно сформированным (привет Интегйту!) вообще не нужен!

Так нужен ли Last-Modified или нет?

Вообще нужен. Но важно понимать, что не сам заголовок играет какую-либо роль, а весь сценарий условных запросов, который должен быть реализован сайтом до конца. Именно в этом случае мы получим высокую скорость индексации сайта.

Но зачастую реализовать это в готовой CMS бывает весьма затруднительно. Возможно для этого потребуется довольно значительные изменения кода самой CMS.

Хотя для ряда CMS это можно реализовать включением кэширования страниц. Если CMS кэширует страницы, создавая и отдавая фактически статичные файлы, то сам веб-сервер будет правильно отвечать на условные запросы. Например, в WordPress это можно реализовать с помощью плагина WP Super Cache :

Проверим его в работе. Я включил этот плагин, открыл браузер в анонимном режиме и сделал два запроса одной страницы. Хорошо видно, что второй ответ правильный — 304 Not Modified:

Вместо заключения

Таким образом, мы разобрались с заголовком Last-Modified. Во-первых, он должен передавать информацию о дате и времени реального изменения документа. Во-вторых, крайне важна реакция сервера на условный запрос с заголовком If-Modified-Since.

Ну и поменьше слушайте сеошников, которые не знают элементарных основ работы интернета.

Многие разработчики при создании сайтов забывают про очень полезный заголовок Last-Modified, благодаря которому можно оптимизировать загрузку web-страниц и облегчить работу поисковым роботам. Далее я постараюсь восполнить этот досадный пробел.

Для чего нужен заголовок Last-Modified?

Функцией заголовка как можно догадаться из названия служит информирование клиента о дате последней модификации web-документа. Исходя из спецификации rfc 2616, клиент может «спросить» у веб сервера не изменилась ли страница с определенного числа, послав серверу заголовок «If-Modified-Since». Если страница не изменилась сервер возвращает только заголовок «304 Not Modified», в противном случае – сервер возвращает заголовок «200 OK» и тело страницы. Как видно, выгода на лицо как для сервера, так и для клиента: браузер не будет грузить страницу снова и снова, а веб сервер будет отдавать меньше данных.

Какие сайты индексируются лучше? Динамические или статичные?

Пару лет назад среди SEO-шников водились споры по поводу того, какие сайты индексируются лучше? Динамические, написанные например на php, или статичные, без использования языков программирования. Зная о заголовке Last-Modified, можно ответить на этот вопрос. Все дело в том, что веб сервер сам обрабатывает заголовок «If-Modified-Since» если файл статичный. В случае динамической генерации страницы вся ответственность за ответ ложится на язык программирования и разработчика. А так как разработчик за частую не интересуется этим вопросом, то заголовки не отдаются вовсе.

Как заголовок Last-Modified ускоряет поисковую индексацию?

Все просто, как написано в помощи Яндекса , «робот не сможет получить информацию о том, обновилась ли страница сайта с момента последнего индексирования. А так как число страниц, получаемых роботом с сайта за один заход, ограничено, изменившиеся страницы будут переиндексироваться реже».

Представьте. Есть сайт с 10 тысячами страниц. Сайт написан на php. Не отдается корректно заголок Last-Modified. Поисковой робот не может получить информацию о том, обновилась ли страница сайта с момента последнего индексирования. Что он делает? Индексирует все страницы!!! А не только те, которые изменились.
Конечно! На многих сайтах используют Sitemap . Но Sitemap это рекомендация, помощь поисковому оптимизатору. Заменой заголовка Last-Modified он быть не может!

Настройка и обработка заголовока Last-Modified в php

Для того чтобы веб-сервер передавал php-backend"у заголовок If-Modified-Since необходимо ему от этом сообщить!

Для связки nginx + php так,

location ~ \.php$
{

if_modified_since off;

Fastcgi_pass fcgi;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /<путь > /web$fastcgi_script_name;

fastcgi_pass_header Last-Modified;
include fastcgi_params;
}

Для связки apache + php, так

# If-Modified-Since (if php is not installed as cgi then comment lines below)
RewriteRule .* -
RewriteRule .* -

* This source code was highlighted with Source Code Highlighter .


Если php работает как модуль, то ничего настраивать не надо!

Простой php-код обработки запроса If-Modified-Since,

$qtime = isset($_SERVER["HTTP_IF_MODIFIED_SINCE" ])? $_SERVER["HTTP_IF_MODIFIED_SINCE" ]:"" ;

$modified = substr(gmdate("r" , $timestamp), 0, -5)."GMT" ;

if ($hdr == $modified)
{
header ("HTTP/1.1 304 Not Modified " );
header ("Last-Modified: $modified" );
exit();
}
header ("Last-Modified: $modified" );
//render

* This source code was highlighted with Source Code Highlighter .

Как обрабатывать запрос If-Modified-Since в symfony?

В symfony уже предусмотрен механизм обработки заголовка. Все что нужно разработчику, так это передать в объект sfWebResponse заголовок. В случае его указания фрейморк все сделает сам.
$datestamp = time();
$response->setHttpHeader("Last-Modified" , $response->getDate($datestamp));

* This source code was highlighted with Source Code Highlighter .


Так как на странице как правило располагается разный контент, то я написал метод, который выставляет самый поздний из переданных заголовков!
static public function setLastModified($datestamp)
{
$response = sfContext::getInstance()->getResponse();
$request = sfContext::getInstance()->getRequest();

if (is_array($datestamp))
{
rsort($datestamp, SORT_NUMERIC);
$datestamp = $datestamp;
}

if (!$response->hasHttpHeader("Last-Modified" ))
{
$response->setHttpHeader("Last-Modified" , $response->getDate($datestamp));
}
else
{
$origLastModified = strtotime($response->getHttpHeader("Last-Modified" ));
if ($origLastModified < $datestamp)
$response->setHttpHeader("Last-Modified" , $response->getDate($datestamp));
}
}

* This source code was highlighted with Source Code Highlighter .


Его очень удобно использовать в случае, если на странице, например, располагается 3 последних видеролика, 3 последних статьи и там еще что-нибудь. Загружая каждую модель из базы данных, мы можем вызывать метод, и в итоге в ответе получив самую позднюю дату модификации.
Для интересующихся код обработки заголовка находится в классе sfCacheFilter.class.php.

В заключение хочу сказать, что использование заголовка Last-Modified не всегда оправдано. Например, если на сайте 5 тысяч страниц и на каждой находится один и тот же блок с часто меняющимся контентом, использовать заголовок будет бесполезно! В этом случае можно разве что отдавать разные заголовки для клиентов и поисковых роботов. Но как по мне обман роботов ни к чему хорошему не приводит. Ну или убрать этот блок;).

Проверить сайт на корректную обработку заголовка можно

За что я люблю PHP, так это за то, что гениальные вещи на нем пишутся в несколько строчек. В этой заметке я продолжу рассуждать о правильном использовании заголовков в PHP. Если вам не всё равно, как индексируется поисковиками ваш сайт, если вы хотите сэкономить трафик, вы нашли именно то, что нужно.

Как известно, кеширование на стороне браузера сокращает нагрузку на сервер. Но для часто обновляемых страниц у него есть существенный недостаток: информация в кеше может устареть и не соответствовать действительной информации.

Для каждого документа, отдаваемого сервером, желательно выдавать заголовок Last-Modified (в том числе для правильной индексации, например, Яндексом):

$mt = filemtime($file_name); header("Last-Modified: ".gmdate("D, d M Y H:i:s", $mt)." GMT");

Для часто обновляемых страниц (я не говорю «динамических», так как страница может каждый раз собираться интерпретатором PHP, но фактически изменяться крайне редко) можно запретить кеширование следующим набором заголовков:

Function no_cache() { header("Expires: Mon, 26 Jul 1997 00:00:00 GMT"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); }

В принципе, для удовлетворительной работы сайта этого достаточно. Однако вместо полного запрета кеширования лучше применить более гибкий механизм с использованием заголовка If-Modified-Since . Он присутствует в запросе браузера, если в его кеше есть копия документа, и его значение - некая дата изменения этой копии. PHP-скрипт может посмотреть на эту дату и решить, стоит ли отдавать браузеру свежую страницу, или сообщить, что страница не изменилась, отправив ответ 304 Not Modified . Вместе с отправкой заголовка Last-Modified , код примет вид:

$mt = filemtime($file_name); $mt_str = gmdate("D, d M Y H:i:s", $mt)." GMT"; if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) && strtotime($_SERVER["HTTP_IF_MODIFIED_SINCE"]) >= $mt) { header("HTTP/1.1 304 Not Modified"); die; } header("Last-Modified: ".$mt_str); echo $text;

В операторе if мы не использовали проверку на равенство $_SERVER["HTTP_IF_MODIFIED_SINCE"] == $mt_str , а преобразовали дату вида Sun, 28 Jan 2007 07:56:48 GMT в формат unixstamp и сравнивали с датой изменения оригинального документа. Это нужно для решения двух проблем.

Дело в том, что последние версии Opera и Firefox исправно копируют содержимое заголовка Last-Modified ответа сервера в заголовок запроса If-Modified-Since (именно поэтому нам нужно было установить Last-Modified), и проверкой на равенство вполне можно было бы обойтись. Но, как всегда, не обошлось без капризов IE 6. Он к заголовку If-Modified-Since добавляет параметр length , в чем и заключается первая проблема. Ее можно решить применением функции strpos , если бы не вторая проблема - хитрости поисковых роботов. Все они (кроме робота Рамблера, который действует по описанной выше схеме) в заголовке If-Modified-Since (если вообще его используют) передают не значение из Last-Modified , а дату последнего скачивания документа. В такой ситуации уже нельзя обойтись без упомянутого перевода дат в unixstamp (что и делает функция date2unixstamp).

Как же работает кеширование в браузерах? Если оно не запрещено вызовом функции no_cache , то в Firefox и в IE страница сохраняется в кеше, при последующих запросах выдается только она. Чтобы обновить страницу в кеше, нужно нажать комбинацию клавиш Ctrl + F5 , обычная кнопка «Обновить» (F5) не помогает. Нужно отметить, что документы в кеше IE могут храниться очень долго. В Опере страница загружается из кеша при повторном переходе на нее по ссылкам, но кеш очищается по нажатию кнопки «Обновить» или клавиши F5. Следует быть аккуратным, так как CRTL+F5 в Опере - перезагрузка страниц со всех вкладок, которая может затянуться надолго при их большом числе.

Если запретить кеширование страницы функцией no_cache , то Опера и Firefox при обращении к такой странице используют механизм с заголовком If-Modified-Since , и это правильно. То есть кеширование всё равно происходит, но браузер спрашивает у сервера, изменилась ли страница на самом деле, или нет. Однако IE запрет на кеширование воспринимает буквально. В ходе экспериментов стало ясно, что если из трех заголовков no_cache убрать второй, то IE версий 6 и 7 начинает работать так, как нам нужно. Может оказаться полезным корректное использование заголовка Expires . В нем можно установить время, в течение которого будет использоваться только локальная копия документа в кеше. Этот способ позволяет справиться с излишне навязчивым кешированием в IE. Например, чтобы копия в кеше была действительна в течение суток, нужно использовать такой оператор:

Header("Expires: ".gmdate("D, d M Y H:i:s", time() + 86400)." GMT");

Итак, как же использовать все эти возможности протокола HTTP? Обработка заголовка If-Modified-Since полезна в любом случае. Например, Яндекс рекомендует ее использовать. Если вы экономите трафик и если страницы обновляются редко, то запрещать их кеширование не нужно. Можно запретить их кеширование, тогда вместо него произойдет запрос к серверу с If-Modified-Since и 304 ответом. Это немного увеличит трафик, но позволит получать более правильную статистику посещений: пользователь зашел на страницу, а мы ему говорим, что страница не изменилась, но в статистике его учитываем. Если документы обновляются часто, практически всегда стоит запрещать их кеширование. Выдача 304 ответа в большинстве случаев скомпенсирует возможное повышение трафика.

Помимо описанного метода для проверки актуальности копии документа в кеше существует еще один, основанный не на дате изменения страницы, а на уникальном хеш-коде содержимого страницы. Общее название для обоих методов - Conditional Get, вы можете ознакомиться с

HTTP заголовок Last-Modified сообщает клиенту время последнего изменения страницы (объекта). Если клиент (браузер, поисковый робот) получил заголовок Last-Modified , то при следующем обращении к адресу, при условии, что страница (объект) есть в локальном кеше, он добавит вопрос If-Modified-Since (не изменилась ли страница после даты, полученной в Last-Modified). В свою очередь сервер, получив запрос If-Modified-Since должен сверить полученную временную метку с временем последнего изменения страницы и, если страница не изменялась ответить 304 Not Modified .

Экономия Трафика

Если страница не изменилась, то сервер прекратит передачу данных после отправки заголовков с кодом 304 Not Modified , тело страницы, изображения и другие объекты передаваться не будут.

Снижение нагрузки на сервер

Правильная реализация проверки времени последнего изменения страницы может значительно (до 30% и более) сократить нагрузку на сервер. Под правильной реализацией подразумевается проверка времени до начала генерации страницы на динамическом сайте. В таком случае все действия для генерации страницы (запрос контента из базы данных, парсинг шаблонов, получение комментариев и др) выполняться не будут. Особенно это актуально для сайтов с высокой посещаемостью и долгой продолжительностью визита пользователя. Пример: пользователь находится на сайте спортивных новостей и постоянно обновляет главную страницу в ожидании публикации результата матча. За несколько минут страница может быть запрошена и получена десятки раз. Если заголовок Last-Modified отдается и запрос If-Modified-Since обрабатывается правильно, то реально страница будет передана один раз, а на все последующие запросы будет выдан ответ 304 Not Modified .

Ускорение индексации поисковыми системами

Поисковые системы через руководство для вебмастеров рекомендуют отсылать заголовок Last-Modified и правильно обрабатывать If-Modified-Since .


Убедитесь, что ваш веб-сервер поддерживает HTTP-заголовок If-Modified-Since . Этот заголовок позволит веб-серверу сообщать Google, изменилось ли содержание сайта со времени последнего сканирования. Поддержка данной функции сократит нагрузку на пропускную способность и издержки.

Следите за корректностью http-заголовков. В частности, важно, содержание ответа, который сервер отдает на запрос if-modified-since . Заголовок Last-Modified должен отдавать корректную дату последнего изменения документа. Если сервер не выдает дату последней модификации документа, ваш сайт будет проиндексирован, но:
- в результатах поиска не будет показываться дата рядом со страницами вашего сайта;
- при сортировке по дате сайт не будет виден большинству пользователей;
- робот не сможет получить информацию о том, обновилась ли страница сайта с момента последнего индексирования. А так как число страниц, получаемых роботом с сайта за один заход, ограничено, изменившиеся страницы будут переиндексироваться реже.