Блог/Last-Modified

Заголовок Last-Modified в Modx Evolution

Автор: Кудашев Сергей

В рамках работы по оптимизации одного проекта наконец дошли руки до внедрения Last-Modified на сайте с Modx Evolution. Внедрение правильной обработки данного заголовка не только будет сообщать о дате последнего изменения документа. Правильная реализация Last-Modified должна так же снизить нагрузку на сервер и положительно отразиться на индексировании сайта поисковыми системами, что напрямую следует из рекомендаций Яндекса. Возможно данное нововведение положительно отразится и на позициях сайта.

Для того, чтобы узнать, каким образом заголовок Last-Modified сможет сократить нагрузку на сервер, обратимся к теории. Первое обращение к сайту роботом поисковой системы осуществляется по HTTP протоколу с использованием GET метода (в нашем случае мы будем рассматривать робота, но то же будет актуально для любого программного обеспечения умеющего работать с If-Modified-Since и Last-Modified). При этом данный запрос обязательно включает в себя адрес страницы, которую следует отдать роботу. Если посмотреть упрощенно, то сервер проверяет наличие данной страницы, формирует ответ и контент страницы. При этом ответ на запрос будет содержать специальный номерной индентификатор, называемый HTTP status code (код состояния HTTP), по которому мы можем определить, например, были ли проблемы при обращении к сайту или нет.

HTTP status code (код состояния HTTP) термин из области телекоммуникаций, в случае с HTTP протоколом представляет из себя трехзначное десятичное число. Первая цифра данного числа является идентификатором класса состояния, по которому можно сразу определить, к какой группе состояний относится данный код. Последующие цифры указывают конкретный статус. За кодом, как правило, следует фраза с пояснениями к данному коду. Ознакомиться с кодами состояния можно в RFC 2068, посвященному протоколу HTTP/1.1.

Если посмотреть в этот момент на работу сервера, то если кратко, сервер, в зависимости от настроек, определит, в какой папке располагается сайт. После определения папки будет определено, существует ли данная страница (статическая страница), если нет, и надо ли прибегать к вызову какой-то другой страницы, чтобы через какой-то язык программирования была сформирована запрашиваемая страница (динамическая страница). В нашем случае с Modx Evolution для формирования любой страницы используется обращение к index.php с GET параметром q. После чего управление передается движку, который по завершению обработки запроса извещает сервер о готовности отослать заголовок и данные.

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

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

Вот реализация плагина LastModified для Modx Evolution, который справляется с этой задачей.

<?php
$e = &$modx->event;
if($e->name!='OnWebPagePrerender') return;

$dtm = ($modx->documentObject['editedon'])?$modx->documentObject['editedon']:$modx->documentObject['createdon'];
//$modx->logEvent('0', 2, $_SERVER['REQUEST_URI'].' use '.$dtm.' date', '403');
if(empty($dtm)) { return; }
if(!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])){
	$ltm = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
	if($dtm <= $ltm){
		header('HTTP/1.0 304 Not Modified');
		header('Last-Modified: '.gmdate('D, d M Y H:i:s',$dtm).' GMT');
		header('Cache-control: private, max-age=3600');
		header('Expires: '.gmdate('D, d M Y H:i:s',time()+3600));
		exit();
	}
}
header('Last-Modified: '.gmdate('D, d M Y H:i:s',$dtm).' GMT');
header('Cache-control: private, max-age=3600');
header('Expires: '.gmdate('D, d M Y H:i:s',time()+3600));
return;

Данный плагин вешается на событие OnWebPagePrerender, после чего получает дату последнего изменения документа. Плагин проверяет наличие If-Modified-Since в запросе и при его наличии отдает заголовок 304 Not Modified и прекращает работу, что нам и требовалось. В скором времени планирую внедрить подобное решение для MODX Revolution.

Комментарии (3)

  1. Sergey13 сентября 2020, 14:03(Комментарий был изменён)#
    Пробовал для своего сайта про бетон scales-nn.ru Evo — ошибка php
    1. Sergey13 сентября 2020, 14:13#
      Сори, разобрался, работает
      1. Sergey13 сентября 2020, 14:15#
        Но неправильно, для только что отредактированного материала выдает Not modified:

        HTTP/1.1 304 Not Modified
        Date: Sun, 13 Sep 2020 11:14:19 GMT
        Server: nginx/1.14.1
        Connection: close
        Cache-Control: private, max-age=3600
        Set-Cookie: evo1h53dgl=8f52ae36e55e95439870343b392a1e2a; path=/; secure; HttpOnly, yams_lang=ru; expires=Sun, 20-Sep-2020 11:14:19 GMT; path=/, yams_lang=ru; expires=Sun, 20-Sep-2020 11:14:19 GMT; path=/
        Expires: Sun, 13 Sep 2020 12:14:19
        Получено: 671 байт
        Время загрузки: 0.11361 сек.