Перейти к публикации

304 ответ, на запрос If-Modified-Since, для динамического контента сайта


Рекомендованные сообщения

Неделю назад я пробовал сделать правильный ответ 304, но не получилось. Пробовал самые разные костыли с интернета. При попытке изменить дату и проверить 304, получаю 200 даже если не было изменений, ну если просто проверить ответ сервера то любой новость выдавал 304 не смотря на обновленный контент.

Проще говоря у меня все получилось наоборот :( 

Еще в начале были проблемы с Last-Modified. Сервер не выдавал такую инфу, долго искал, наткнулся на форум 2017 года, там говорили про SSI в настройках WWW домена в ISP. Отключил эту функцию и все заработало, Last-Modified начал работать, но беда, голый Last-Modified никак не поможет...

Так что лучше обратитесь к разработчикам с ТЗ, в самом DLE нет такой функций. Если что я готов поддержать / разделить расходы если найдете исполнителя.

Изменено пользователем Хоббит
Ссылка на сообщение
Поделиться на других сайтах

Есть ли от этого смысл? Но как-то так, в корневой index.php (не через систему плагинов) после закомментированных строк */ ниже вставить:

/* ========= Last-Modified START ==================== */
header('Expires: '.gmdate('D, d M Y H:i:s', time() + 10800).' GMT');
header('Cache-Control: no-cache, must-revalidate');
$mt = filemtime($file_name);
$mt_str = gmdate("D, d M Y H:i:s ")."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;
header("Vary: Accept-Encoding");
header("Accept-Encoding:gzip,deflate,sdch");
/* ========= Last-Modified END ====================== */

SSI в настройках домена - отключить

+ 10800 в первой строчке это Москва (+3 часа). Time zone list / Epoch to time zone converter

Проверка If-Modified-Since

MfK7VWFx.jpg

 

Или так:

$LastModified_unix = 1294844676; // время последнего изменения страницы
$LastModified = gmdate("D, d M Y H:i:s \G\M\T", $LastModified_unix);
$IfModifiedSince = false;
if (isset($_ENV['HTTP_IF_MODIFIED_SINCE']))
    $IfModifiedSince = strtotime(substr($_ENV['HTTP_IF_MODIFIED_SINCE'], 5)); 
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
    $IfModifiedSince = strtotime(substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 5));
if ($IfModifiedSince && $IfModifiedSince >= $LastModified_unix) {
    header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
    exit;
}
header('Last-Modified: '. $LastModified);

 

Изменено пользователем Captain
Ссылка на сообщение
Поделиться на других сайтах
1 час назад, Captain сказал:

Есть ли от этого смысл? Но как-то так, в корневой index.php (не через систему плагинов) после закомментированных строк */ ниже вставить:



/* ========= Last-Modified START ==================== */
header('Expires: '.gmdate('D, d M Y H:i:s', time() + 10800).' GMT');
header('Cache-Control: no-cache, must-revalidate');
$mt = filemtime($file_name);
$mt_str = gmdate("D, d M Y H:i:s ")."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;
header("Vary: Accept-Encoding");
header("Accept-Encoding:gzip,deflate,sdch");
/* ========= Last-Modified END ====================== */

SSI в настройках домена - отключить

+ 10800 в первой строчке это Москва (+3 часа). Time zone list / Epoch to time zone converter

Проверка If-Modified-Since

MfK7VWFx.jpg

 

Или так:



$LastModified_unix = 1294844676; // время последнего изменения страницы
$LastModified = gmdate("D, d M Y H:i:s \G\M\T", $LastModified_unix);
$IfModifiedSince = false;
if (isset($_ENV['HTTP_IF_MODIFIED_SINCE']))
    $IfModifiedSince = strtotime(substr($_ENV['HTTP_IF_MODIFIED_SINCE'], 5)); 
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
    $IfModifiedSince = strtotime(substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 5));
if ($IfModifiedSince && $IfModifiedSince >= $LastModified_unix) {
    header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
    exit;
}
header('Last-Modified: '. $LastModified);

 

Теперь откройте webmaster.yandex.ru и проверьте ответ сервера изменив дату на любую другую кроме сегодняшнего дня. Получите 200 вместо 304.

По идее сайт должен отдавать 304 если новость не изменился, особенно актуально для поисковых ботов, поможет экономить караулинговый бюджет. 

Изменено пользователем Хоббит
Ссылка на сообщение
Поделиться на других сайтах

zGF2iajZ.jpg

 

$LastModified_unix = gmdate('D, d M Y H:i:s \G\M\T', time());
$LastModified = gmdate("D, d M Y H:i:s \G\M\T", $LastModified_unix);
$IfModifiedSince = false;
if (isset($_ENV['HTTP_IF_MODIFIED_SINCE']))
    $IfModifiedSince = strtotime(substr($_ENV['HTTP_IF_MODIFIED_SINCE'], 5)); 
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
    $IfModifiedSince = strtotime(substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 5));
if ($IfModifiedSince && $IfModifiedSince >= $LastModified_unix) {
    header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
    exit;
}
header('Last-Modified: '. $LastModified);

 

Ссылка на сообщение
Поделиться на других сайтах
18.11.2020 в 05:33, Captain сказал:

 


$LastModified_unix = gmdate('D, d M Y H:i:s \G\M\T', time());
$LastModified = gmdate("D, d M Y H:i:s \G\M\T", $LastModified_unix);
$IfModifiedSince = false;
if (isset($_ENV['HTTP_IF_MODIFIED_SINCE']))
    $IfModifiedSince = strtotime(substr($_ENV['HTTP_IF_MODIFIED_SINCE'], 5)); 
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
    $IfModifiedSince = strtotime(substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 5));
if ($IfModifiedSince && $IfModifiedSince >= $LastModified_unix) {
    header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
    exit;
}
header('Last-Modified: '. $LastModified);

 

Кажется я не так выразился, прописал ваш код.

1. Дата новости: https://ibb.co/Sm2cKPw

2. Ответ сервера: https://ibb.co/Nm8dgqF

3. Изменяем дату при обращений: https://ibb.co/prctMwK

Первый ответ сервера без изменения даты обращения работает как надо (200). Второй ответ сервера неправильно (304) потому что бот обращался с датой 16 ноября 12:00, 2020 в то время новость изменил контент и имеет дату в первом скриншоте. Получается если бот индексировал ваш сайт 15 числа, то внесенные новые изменения не будут индексироваться т.к. сервер выдает 304 как будто Last-Modifed не изменился (а этот параметр есть, см. второй скрин)

Ссылка на сообщение
Поделиться на других сайтах
2 минуты назад, Zhur сказал:

@celsoft может рассмотрите внедрение в новые версии скрипта из коробки? Чтобы мы не мучились с костылями. 

Это вряд-ли, очень и очень маловероятно, мб через пару лет, или вообще 5-10 лет придётся ждать. 

Мне тоже интересен этот вопрос, если вдруг подумаете написать ТЗ и найти исполнителя, я мог бы разделить часть расхода на реализацию. 

Ссылка на сообщение
Поделиться на других сайтах
5 часов назад, Zhur сказал:

может рассмотрите внедрение в новые версии скрипта из коробки? Чтобы мы не мучились с костылями. 

Нет, потому как это бессмысленная трата времени, и то что вы пытаетесь сделать также бессмысленно.

Делается это для снижения нагрузки. Что невозможно в данном случае. Чтобы отдать правильно, нужно почитать новость из БД, сравнить ее дату, и после этого отдавать тот или иной код. В данном случае проще и дешевле в плане нагрузки отдать сразу 200 код, и не "страдать" ерундой, не экономя по своей сути нечего.

Ссылка на сообщение
Поделиться на других сайтах
10 часов назад, celsoft сказал:

Нет, потому как это бессмысленная трата времени, и то что вы пытаетесь сделать также бессмысленно.

Делается это для снижения нагрузки. Что невозможно в данном случае. Чтобы отдать правильно, нужно почитать новость из БД, сравнить ее дату, и после этого отдавать тот или иной код. В данном случае проще и дешевле в плане нагрузки отдать сразу 200 код, и не "страдать" ерундой, не экономя по своей сути нечего.

А что скажете про ETag? https://habr.com/ru/company/edison/blog/509484/

Ссылка на сообщение
Поделиться на других сайтах
4 минуты назад, Хоббит сказал:

А что скажете про ETag?

В настройках nginx например это включается и отключается. Это уже серверная настройка.

Ссылка на сообщение
Поделиться на других сайтах
17 часов назад, celsoft сказал:

Нет, потому как это бессмысленная трата времени, и то что вы пытаетесь сделать также бессмысленно.

То есть сайты на 100 000 страниц которым нужно экономить краулинговый бюджет обреченны?

 

17 часов назад, celsoft сказал:

Делается это для снижения нагрузки.

Речь шла не о нагрузке, а о том чтобы отдавать поисковому боту только нужные страницы, а не гонять по всем подряд. К тому же можно подумать о том чтобы реализовать включение и отключение функции по кнопке, кому не нужно - не используют, кому нужно - используют.

Ссылка на сообщение
Поделиться на других сайтах
18 часов назад, Zhur сказал:

То есть сайты на 100 000 страниц которым нужно экономить краулинговый бюджет обреченны?

Вообще то он не экономится а наоборот повышается, и к эффективным методам относится запрет на индексацию ненужного а не 304 код ответа. Примерно следующее:

Цитата

Найти страницы, на которых частотность кластера ключевых запросов стремится к 0. К примеру, такими страницами могут быть страницы фильтров. Следует закрыть найденные страницы от индексации;

Найти технические страницы сайта с кодом ответа сервера 200. Оптимизировать систему управления контентом сайта, чтобы такие страницы не создавались или были закрыты от индексации краулером поисковой системы;

Закрыть от индексации неактуальные и ненужные страницы. Например, страницы которые не несут смысловой нагрузки и/или по которым нет возврата на инвестиции.

 

Ссылка на сообщение
Поделиться на других сайтах

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

Короткий ответ: 
На текущий момент, правильная работа с протоколом клиентского кэширования версии HTTP/1.1 является промышленным стандартом, реализация которого обязана быть в любой системе где:

  1. нет обработки данных в реального времени
  2. взаимодействие клиента с сервером осуществляется на базе протокола HTTP до второй версии включительно

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

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

То есть
Пользователи правы, а представитель поддержки нет.
Причем заявления представителя говорят об отсутствии компетенции и в этой области, о чем свидетельствуют его технически безграмотные ответы. 

Длинный ответ

Скрытый текст

 

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


Сначала рассмотрим ситуацию, когда наше веб приложение сделано со всеми возможными архитектурными ошибками.

В упрощенном виде запрос клиента к серверу выглядит как:

  1. Пришел запрос к серверной части  
  2. Серверная часть решив задачи транспортного уровня транслирует запрос логике проекта
  3. Логика проекта в соответствии  с условиями запроса приготовила данные и транслировала данные шаблонизатору
  4. Шаблонизатор на основе полученных данных сформировал тело ответа и вернул его серверной части
  5. Серверная часть вернула данные клиенту и завершила процессы транспортного уровня. 

В случае же запроса с установленными  заголовками кэширования эта же схема становиться

  1. Пришел запрос к серверной части  
  2. Серверная часть решив задачи транспортного уровня транслирует запрос логике проекта
  3. Логика проекта в соответствии в соответствии с запросом приготовила данные, поняла что они не изменялись и транслировала серверной части - ответ 304
  4. Шаблонизатор на основе полученных данных сформировал тело ответа и вернул его серверной части
  5. Серверная часть вернула клиенту 37 байт с кодом ответа 304 - используйте кэш.

Как видно из этой очень примитивной схемы для случая, когда проект построен со всеми возможными архитектурными ошибками, мы получаем экономию на 4 фазе работы шаблонгизатора, не считая экономии на издержках связанных с доставкой кода работы шаблонизатора.  

Как видно из выше сказанного, даже на самом примитивном уровне, не существует никаких условий при которых бы реализация корректной работы с клиентским кэшированием протокола HTTP/1.1 приводило  бы к ситуации когда ответ:

23.11.2020 в 01:00, celsoft сказал:

Нет, потому как это бессмысленная трата времени, и то что вы пытаетесь сделать также бессмысленно.

Делается это для снижения нагрузки. Что невозможно в данном случае. Чтобы отдать правильно, нужно почитать новость из БД, сравнить ее дату, и после этого отдавать тот или иной код. В данном случае проще и дешевле в плане нагрузки отдать сразу 200 код, и не "страдать" ерундой, не экономя по своей сути нечего.

был бы хотя бы на йоту правильным. 

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

Ситуация с правильной архитектурой.
протокол клиентского кэширования HTTP/1.1 спроектирован таким образом, что, в ситуациях когда браузер получает все необходимые данные о состоянии проекта, он не будет делать запросов вообще. 
Конечно не всегда проект, может предоставить точную информацию о будущих изменениях заранее, и естественно в этом случае есть выходы из положения. 

Первый заключается в организации работы с кэшем таким образом, что бразуер при самом негативном сценарии осуществляет принудительную ревалидацию кэша, при каждом запросе. 
Серверная часть при правильной архитектуре, почти ничего вообще не знает о логике работы проекта. Она просто берет готовый сформированный для нее кэш и отдает его в соответствии с параметрами протокола запроса.

Иными словами, проект, в момент изменения данных, сразу формирует необходимые данные для кэширования и помещает их в транзитное хранилище. С которым и работает уже веб сервер. 

Такой WEB сервер как Apache предоставляет из коробки все возможные варианты обслуживания кэшей разного уровня с разными харнилицами. WEB сервер Nginx обладает на много более скудными возможностями, но более чем достаточными для того чтобы  решать те же задачи почти на том же уровне.

Подчеркиваю. Пользователь который в состоянии нажимать кнопки в административной части, при правильно построенной платформе, мог бы сам запускать кэш достаточного уровня сложности не обладая для этого никаким професиональными навыками, а только желанием разобраться. 

При такой архитектуре, из всей схемы описанной ранее остается только часть первой фазы связанной с издержками на установку соединения. 

Далее о работе с поисковыми системами.

О крауленговом бюджете
Даже если вынести за скобки всю прохладную историю написанную выше, проект может находится в ситуации, когда он будет напрямую зависеть от органического трафика. То есть от работ поисковых машин.

Современные поисковые машины, все до единой, при повторном запросе на индексацию какого либо контента, устанавливают заголовок if-modified-since равным дате предыдущего сканирования этого же ресурса. Делается это с одной целью - получать оперативную информацию о том, изменился ресурс или нет.  
Что, как правильно писали люди выше, в самом базовом варианте экономит краулинговый бюджет,

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

Правильная настройка ответа на  заголовок if-modified-since является сейчас промышленным стандартом для решения подобных задач, потому что позволяет проекту получать бюджеты в сотни тысяч страниц в сутки без необходимости какой либо серьезной работы в этом направлении.

Кроме краулингового бюджета
Сам по себе крауленговый бюджет это безусловно хорошо, но на нем все не заканчивается. Когда поисковая машина получает устойчивую статистику успешных сессий подобного рода, любая ситуация требующая оперативной индексации какого либо нового контента решается в течении 5 минут. То есть проект, получает возможность индексироваться с латенси не более 5 минут после публикации, используя механизмы cache api поисковой системы, или пользуясь более архаичными способами связанные с  использованием rest api для добавления новых карт сайта  в автоматическом режиме.

А не ждать когда автоматика решит найти новую страницу.

О заголовке ETag

Ответ представителя в этой части как нельзя лучше демонстрирует отсуствие компетенции в этой области.

23.11.2020 в 12:08, celsoft сказал:

В настройках nginx например это включается и отключается. Это уже серверная настройка.


Спецификация заголовка ETag протокола HTTP/1.1 разрабатывалась с целью, дать программистам любого проекта, организовывать схемы взаимодействия их проекта с клиентом на базе той логики, которая нужна программисту проекта,  а не привязываться  к дате изменения данных. WEB сервер в этой схеме никак не участвует по причине того, что программисты WEB серверов не пророки чтобы заложить в него все идеи будущих естествоиспытателей.  

То что NGinx  или любой другой WEB сервер, из коробки подставляет контрольную сумму ресурса в качестве значения заголовка ETag ровным счетом ни на что не влияет, кроме бесполезной траты ресурсов на постоянный перерасчет контрольных сумм. Один из регулярных вопросов на собеседований на должность джуниор системного администратора, это ваши первые шаги после установки веб сервера, где отлюкчение формирования заголовка ETag один из пунктов. 

 

 

 

 

Изменено пользователем demimurych
исправление опечаток и ошибок
Ссылка на сообщение
Поделиться на других сайтах

Реально многим ли нужно это?
От этого зависит реализация в том числе и сторонними разработчиками.

Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, Mr. Bot сказал:

Реально многим ли нужно это?
От этого зависит реализация в том числе и сторонними разработчиками.

Если сайт имеет меньше 1000 страниц, это вовсе не нужно (цитата с Google). 

Эффект заметен если страниц больше 100к. Да можно сторонними разработчиками, но много ли желающих и знающих как все это грамотно реализовать. 

Ссылка на сообщение
Поделиться на других сайтах
15 часов назад, Хоббит сказал:

Если сайт имеет меньше 1000 страниц, это вовсе не нужно (цитата с Google). 

Эффект заметен если страниц больше 100к. Да можно сторонними разработчиками, но много ли желающих и знающих как все это грамотно реализовать. 

Собирайтесь, организовывайтесь, делайте ТЗ, пишите в личку)

Ссылка на сообщение
Поделиться на других сайтах
24.11.2020 в 21:18, demimurych сказал:

То есть
Пользователи правы, а представитель поддержки нет.
Причем заявления представителя говорят об отсутствии компетенции и в этой области, о чем свидетельствуют его технически безграмотные ответы. 

Ну ну. Серверная же часть у них за счет воздуха работает, а для просчета используется Апач, ага ))) Пусть для начала просчитают и реализует корректное отслеживание всех возможных изменений на странице, публикаций, комментариев, доп. блоков. А потом говорят о технически безграмотных ответах.

Ссылка на сообщение
Поделиться на других сайтах
  • 2 недели спустя...
19.11.2020 в 21:33, Хоббит сказал:

$LastModified_unix = gmdate('D, d M Y H:i:s \G\M\T', time());

Тут не правильно! Нужно брать дату последнее редактирование поста из таблицы, а не текущее время.

Чисто для самого поста:
В файле engine/modules/functions.php

Найти:

if($_DOCUMENT_DATE) {
  @header ("Last-Modified: " . date('r', $_DOCUMENT_DATE) ." GMT");
}

Заменить на:

/**
 * Last-Modified or 304 Not Modified
 */
if ($_DOCUMENT_DATE) {

	$LastModified_unix = $_DOCUMENT_DATE; // время последнего изменения страницы
	$LastModified = gmdate("D, d M Y H:i:s \G\M\T", $LastModified_unix);
	$IfModifiedSince = false;

	if (isset($_ENV['HTTP_IF_MODIFIED_SINCE']))
		$IfModifiedSince = strtotime(substr($_ENV['HTTP_IF_MODIFIED_SINCE'], 5));

	if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
		$IfModifiedSince = strtotime(substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 5));

	if ($IfModifiedSince && $IfModifiedSince >= $LastModified_unix) {
		header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
		die();
	}

	header('Last-Modified: '. $LastModified);

} // End

Можете оформить в виде плагина сами, всё будет работать правильно. 

Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете опубликовать сообщение сейчас, а зарегистрироваться позже. Если у вас есть аккаунт, войдите в него для написания от своего имени.

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

×
×
  • Создать...