Skip to content

Instantly share code, notes, and snippets.

@aktaumag
Created March 13, 2021 21:00
Show Gist options
  • Save aktaumag/4e036bff9cd32a74dc267800091e2c65 to your computer and use it in GitHub Desktop.
Save aktaumag/4e036bff9cd32a74dc267800091e2c65 to your computer and use it in GitHub Desktop.
Обеспечение корректной обработки If-Modified-Since имеет чрезвычайно важную роль, если мы боремся за органический трафик.
@aktaumag
Copy link
Author

aktaumag commented Mar 13, 2021

Проверяем If-Modified-Since

Способы диагностирования корректной обработки сервером этого заголовка.

Online
Для проверки можно воспользоваться online сервисом: https://last-modified.com/ru/if-modified-since.html

Curl
смотрим параметр Last-Modified

$ curl -I https://example.com/img/image.jpg

передаем текущую дату в формате dd mmm YYYY (дата в одинарных или двойных кавычках):

$ curl -I -z "Thu, 11 Mar 2021 18:55:58 GMT" https://example.com/img/image.jpg
$ curl -I -z '13 Jan 2020' https://example.com/img/image.jpg

Ответ должен быть 304

HTTP/1.1 304 Not Modified 
Expires: Tue, 02 Mar 2032 13:40:46 GMT
Cache-Control: max-age=383616000, public

JavaScript / Node / Google Developer Tools
Открыв любой агент который поддерживает выполнение JS кода, например Developer Tools в браузере Google Chrome, достаточно в контексте ресурса выполнить команду

fetch("https://examples.com", {
headers: {
"if-modified-since": new Date().toGMTString()
}
})
.then(function(r) {
r.status === 304 ? console.log(
  "%cAll fine. Response status code: %d. \nResponse object: %O",
  "color: green",
   r.status,
   r)
  : console.log("%cResponse status code: %d when expected: 304.
   \nResponse object: %O",
    "color:red",
    r.status,
    r);
})
.catch(function(r) {
    console.log("%cSomthing wrong\n" + r, "color:red");
});

Примеры конфигураций

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

Apache
Для типичного набора статических ресурсов (изображения, CSS и JS файлы и т.д.) устанавливаем время жизни кеша в 1 год,

<filesMatch "(?i).(ico|pdf|flv|jpg|jpeg|png|gif|js|css|webp)$">
    Header set Cache-Control "max-age=383616000"
</filesMatch>

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

В случае если необходим expires, для файла с типом jpg

ExpiresActive On
ExpiresByType image/jpeg "now plus 148 months"

Незабываем удостовериться в том, что модуль expires подключен и в конфигурации Apache определен тип файла заданный в правиле expires (image/jpeg):

0	beshort		0xffd8		image/jpeg

Nginx

location ~* ^.+\.(jpg | gif | png | css | js | woff | webp )$ {
expires max;
}

LightHttpd

server.modules  = (
"mod_expire",
"mod_setenv",
expire.url = ( "/images/" => "access plus 1 month" )
$HTTP["url"] =~ "^/" { expire.url = ( "" => "access 1000 days" ) }
setenv.add-response-header += ("Cache-Control" => "public")
)

PHP
Управление заголовками осуществляется посредством оператора header
php.net header - Manual: https://www.php.net/manual/ru/function.header.php

<?php header("Cache-Control: max-age=383616000"); ?>

Популярные фреймворки
Если разработка ведется с использованием какого-либо фреймворка (Laravel, Yii, Ruby и т.д.) то решать вопросы заголовков для формируемых страниц нужно используя предусмотренные фреймворком интерфейсы.

Например для Yii2 код выглядеть может следующим образом:

public function behaviors() {
return [
    [
        'class' => 'yii\filters\HttpCache',
        'only' => ['index'],
        'lastModified' => function ($action, $params) {
            $q = new \yii\db\Query();
            return $q->from('post')->max('updated_at');
        },
    ],
];
}

Nginx и If-Modified-Since

Конфигурация Nginx, по умолчанию, обслуживает запрос с if-modified-since только в случае указания даты абсолютно идентичной той, которая отдается при запросе. Что естественно приводит к ситуации, когда поисковые машины, которые указывают дату последнего сканирования ресурса, получают вместо ожидаемого кода 304, код 200. То есть инициируют процедуру переиндексации.

Причиной этому служит значение по умолчанию для параметра

if_modified_since exact;

Нужно в файле конфигурации Nginx изменить значение exact на

if_modified_since before;

Документация Nginx о if_modified_since: http://nginx.org/ru/docs/http/ngx_http_core_module.html#if_modified_since

Письмо хостеру
В случае если доступа к конфигурационным файлам Nginx хостер не предоставляет, ему можно отправить следующее письмо:

Добрый день!
Домен: 

Проверяю логотип: 
На этом ресурсе: https://last-modified.com/ru/if-modified-since.html

Текущая конфигурация Nginx, при запросе статического контента,   (.jpg .png .css и т.д.) с установленным заголовком if_modified_since корректно работает только если прям точно совпадают даты из заголовка if_modified_since с датой из заголовка last-modified.

Происходит это потому, что по умолчанию Nginx работает с настройкой:
if_modified_since exact;

Очень прошу Вас исправить это, то есть прописать явно в конфигурации Nginx настройку:
if_modified_since before;

Ссылка на документацию Nginx:
http://nginx.org/ru/docs/http/ngx_http_core_module.html#if_modified_since

Вот список расширений для статических файлов:
jpg|jpeg|gif|swf|png|avif|webp|ico|mp3|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|avi|ppt|txt|tar|mid|midi|wav|bmp|rtf|wmv|mpeg|mpg|mp4|m4a|spx|ogx|ogv|oga|webm|weba|ogg|tbz|js|7z|woff|woff2|ttf|svg|iso

Спасибо Demi Murych: https://www.youtube.com/watch?v=r5C30aM2Nz8

@aktaumag
Copy link
Author

aktaumag commented Mar 14, 2021

Устанавливаем заголовки при помощи PHP

Важно: Не применять это к корзине, избранным и прочим динамическим страницам, которые меняются в зависимости от параметров и т.д. Все такие страницы всё равно не должны обходить поисковые боты.

// Если в бвзе данных есть дата обновления, то записываем её в переменную $page_data->updated_at = '2021-03-14 01:05:03';
// Проверяем сразу дату изменения, так как если не нужно генерировать страницу, то и ресурсы тратить не надо
if(isset($page_data->updated_at)){
    $LastModified_unix = strtotime($page_data->updated_at);
    // Даже если известна точная дата последнего изменения страницы, то всё равно можно раз в месяц выдавать 200 ответ сервера для переиндексации. 
    // Вдруг сам шаблон шаблон за это время изменился или ещё что-то

    $wsdday = date("d",$LastModified_unix);
    if($wsdday > 28) $wsdday = 28;
    // mktime(часы, минуты, секунды, месяц, день, год)
    $wstest = mktime(date("H",$LastModified_unix), date("i",$LastModified_unix), date("s",$LastModified_unix), date("m"), $wsdday, date("Y"));
    // 15-ое число текущего месяца
    // Если сформированная дата меньше реальной, то конечно отображаем реальную как есть, а если больше, то используем её
    if($wstest > $LastModified_unix){
        if($wstest < time()){
            // если сформированная дата уже наступила
            $LastModified_unix = $wstest;
        }
        else {
            // если сформированная время больше текущей, то получаем такую-же дету месяц назад
            $wsdm = date("m") - 1;
            $wsdy = date("Y");
            if($wsdm == 0){
                $wsdm = 12;
                --$wsdy;
            }
            $wstest = mktime(date("H",$LastModified_unix), date("i",$LastModified_unix), date("s",$LastModified_unix), $wsdm, $wsdday, $wsdy);
            if($wstest > $LastModified_unix){
                $LastModified_unix = $wstest;
            }
        }
    }
}
else {
    // Формируем каждый понедельник новую дату
    // Имитируя еженедельное обновление
    // mktime(часы, минуты, секунды, месяц, день, год)
    $wstest = mktime(date("m"), date("d"), date("d")+date("m"), date("m"), date("d"), date("Y"));
    $wstoday = getdate();
    if($wstoday['wday'] == 0){
        // если сформированная время больше текущей, то отнимаем 7 дней, 7 минут и 7 секунд
        if(time() < $wstest){
            // если сформированная время больше текущей, то отнимаем 7 дней, 7 минут и 7 секунд
            $LastModified_unix = $wstest - (7*86400+7*60+7);
        }
        else {
            $LastModified_unix = $wstest;
        }
    }
    else {
        $LastModified_unix = $wstest - ($wstoday['wday']*86400+$wstoday['wday']*60+$wstoday['wday']);
    }
}
$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);

@aktaumag
Copy link
Author

aktaumag commented Mar 22, 2021

DLE

Почти в самое начало engine/modules/show.full.php, но когда уже получили переменную $row

if( strtotime($row['date']) > $_TIME || strtotime($row['date']) > $row['editdate']) {
	$LastModified_unix = strtotime($row['date']);
}
elseif(isset($row['editdate']) && $row['editdate'] != 0){
	$LastModified_unix = $row['editdate']; // тут дата сразу в unix формате
}
else {
	$LastModified_unix = strtotime($row['date']);
}

В самое начало engine/modules/main.php

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// wSEO START Michael Nossov // add: Сразу обрабатываю даты последнего изменения, так как может и нет смысла выводить всю страницу и нужно отдать код 304

if(isset($dle_module) && ($dle_module == "main" || $dle_module == "cat" || $dle_module == "catalog" || $dle_module == "showfull")){
	// Применяем эти настройки только к главной, категориям, новостям (чтобы не затрагивать страницы поиска, избранного, ЛК и прочие)
	// Текущее время по гринвичу gmmktime(часы, минуты, секунды, месяц, день, год)
	$wsnaw = gmmktime(gmdate("H"), gmdate("i"), gmdate("s"), gmdate("m"), gmdate("d"), gmdate("Y"));
	
	if(!isset($LastModified_unix)){
		// Если это не статья, то у страницы нет даты изменения и поэтому генерируем сами
		// Для главной имитируем обновление каждый час
		// Для других страниц имитируем обновление каждый день
		
		if ( $dle_module == "main") {
			// если это главная
			// Формируем каждый час новую дату
			$LastModified_unix = gmmktime(gmdate("H"), gmdate("d"), gmdate("d")+gmdate("m"), gmdate("m"), gmdate("d"), gmdate("Y"));
			// Задаём время обновления
			$wsuptimer = 3600;
		}
		else{
			// Формируем каждый день новую дату
			// Имитируя ежедневное обновление
			$LastModified_unix = gmmktime(gmdate("m"), gmdate("d"), gmdate("d")+gmdate("m"), gmdate("m"), gmdate("d"), gmdate("Y"));
			// Задаём время обновления
			$wsuptimer = 86400;
		}
		
		if($wsnaw < $LastModified_unix){
			// если сформированная время больше текущей, то отнимаем нужное время и генерируем дату так, как она была бы сгенерирована в то время
			$wstest = $LastModified_unix - $wsuptimer;
			$LastModified_unix = gmmktime(gmdate("H",$wstest), gmdate("d",$wstest), gmdate("d",$wstest)+gmdate("m",$wstest), gmdate("m",$wstest), gmdate("d",$wstest), gmdate("Y",$wstest));
		}
		
	}
	else {
		// Если это статья у которой известна дата изменения/создания
		// Отдаём её на обновление каждый месяц
		
		$wsdday = gmdate("d",$LastModified_unix);
		if($wsdday > 28) $wsdday = 28; // дата для удобства, так как 28 день есть во всех месяцах
		// Формируем 28-ое число текущего месяца
		$wstemp = gmmktime(gmdate("H",$LastModified_unix), gmdate("i",$LastModified_unix), gmdate("s",$LastModified_unix), gmdate("m"), $wsdday, gmdate("Y"));
		// Если сформированная дата меньше реальной, то конечно отображаем реальную как есть, а если больше, то используем её
		if($wstemp > $LastModified_unix){
			if($wstemp < $wsnaw){
				// если сформированная дата уже наступила
				$LastModified_unix = $wstemp;
			}
			else {
				// если сформированная дата больше текущей, то получаем такую-же дету месяц назад
				$wsdm = gmdate("m") - 1;
				$wsdy = gmdate("Y");
				if($wsdm == 0){
					$wsdm = 12; // Если прошлый месяц получился 0, значит это был декабрь
					--$wsdy; // значит ещё и год отнять надо
				}
				$wstemp = gmmktime(gmdate("H",$LastModified_unix), gmdate("i",$LastModified_unix), gmdate("s",$LastModified_unix), $wsdm, $wsdday, $wsdy);
				if($wstemp > $LastModified_unix){
					$LastModified_unix = $wstemp;
				}
			}
		}
		
	}
	
	// Бывают ситуации, когда дата создания статьи указана больше, чем текущая. Это делается, когда статьи пишутся заранее... они пока не отображаются
	// Поэтому на всякий случай делаю сравнение дат. Выводим заголовки только для опубликованных статей с датой меньше текущей
	if($wsnaw > $LastModified_unix){
		$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);
	}
}
//// wSEO END
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

@aktaumag
Copy link
Author

aktaumag commented Mar 28, 2021

CMS Bitrix

В файле /bitrix/modules/main/lib/httpresponse.php находим функцию public function writeHeaders()

                if($this->lastModified !== null)
		{
			// START wSEO.kz
			// В основном это касается товаров.
			// Если мы знаем дату последнего изменения, то всё равно Отдаём её на обновление каждый месяц
			// Текущее время по гринвичу gmmktime(часы, минуты, секунды, месяц, день, год)
			$wsnaw = gmmktime(gmdate("H"), gmdate("i"), gmdate("s"), gmdate("m"), gmdate("d"), gmdate("Y"));
			
			$LastModified_unix = $this->lastModified->getTimestamp();
			$wsdday = gmdate("d",$LastModified_unix);
			if($wsdday > 28) $wsdday = 28; // дата для удобства, так как 28 день есть во всех месяцах
			// Формируем 28-ое число текущего месяца
			$wstemp = gmmktime(gmdate("H",$LastModified_unix), gmdate("i",$LastModified_unix), gmdate("s",$LastModified_unix), gmdate("m"), $wsdday, gmdate("Y"));
			// Если сформированная дата меньше реальной, то конечно отображаем реальную как есть, а если больше, то используем её
			if($wstemp > $LastModified_unix){
				if($wstemp < $wsnaw){
					// если сформированная дата уже наступила
					$LastModified_unix = $wstemp;
				}
				else {
					// если сформированная дата больше текущей, то получаем такую-же дету месяц назад
					$wsdm = gmdate("m") - 1;
					$wsdy = gmdate("Y");
					if($wsdm == 0){
						$wsdm = 12; // Если прошлый месяц получился 0, значит это был декабрь
						--$wsdy; // значит ещё и год отнять надо
					}
					$wstemp = gmmktime(gmdate("H",$LastModified_unix), gmdate("i",$LastModified_unix), gmdate("s",$LastModified_unix), $wsdm, $wsdday, $wsdy);
					if($wstemp > $LastModified_unix){
						$LastModified_unix = $wstemp;
					}
				}
			}
			// Бывают ситуации, когда дата создания статьи указана больше, чем текущая. Это делается, когда статьи пишутся заранее... они пока не отображаются
			// Поэтому на всякий случай делаю сравнение дат. Выводим заголовки только для опубликованных статей с датой меньше текущей
			if($wsnaw >= $LastModified_unix){
				$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);
				$this->flushHeader(array("Last-Modified", $LastModified));
			}
			// wSEO.kz  Закрыл старый вывод заголовка
			//$this->flushHeader(array("Last-Modified", gmdate("D, d M Y H:i:s", $this->lastModified->getTimestamp()) . " GMT"));
			// END wSEO.kz
		}

В файле header.php от нашего шаблона прописываем в самом начале

//	use \Bitrix\Conversion\Internals\MobileDetect;
	
    if(!CSite::InDir('/product/')){
	    // У продуктов настроены заголовки Last-Modified и If-Modified-Since
        // Поэтому исключаем их из этого обработчика
	    $wstt = 'na';
	    
//	    $detect = new MobileDetect;
//	    $wsua = $detect->getUserAgent();
//	    // Сами заголовки прописываем только для ботов
//	    if (preg_match('/bot|LastModBot|crawl|curl|dataprovider|search|get|spider|find|java|majesticsEO|google|yahoo|teoma|contaxe|yandex|libwww-perl|facebookexternalhit/i', $_SERVER['HTTP_USER_AGENT'])) {
//		    // is bot
//
//	    }
            // Текущее время по гринвичу gmmktime(часы, минуты, секунды, месяц, день, год)
		    $wsnaw = gmmktime(gmdate("H"), gmdate("i"), gmdate("s"), gmdate("m"), gmdate("d"), gmdate("Y"));
		
		    if(CSite::InDir('/catalog/') || $APPLICATION->GetCurPage(false) == '/') {
			    $wstt = 'catalog or main';
			    // если это главная или каталог
			    // Формируем каждый час новую дату
			    $LastModified_unix = gmmktime(gmdate("H"), gmdate("d"), gmdate("d")+gmdate("m"), gmdate("m"), gmdate("d"), gmdate("Y"));
			    // Задаём время обновления
			    $wsuptimer = 3600;
		    }
		    else {
			    $wstt = 'not catalog and not main and not product';
			    // Формируем каждый день новую дату
			    // Имитируя ежедневное обновление
			    $LastModified_unix = gmmktime(gmdate("m"), gmdate("d"), gmdate("d")+gmdate("m"), gmdate("m"), gmdate("d"), gmdate("Y"));
			    // Задаём время обновления
			    $wsuptimer = 86400;
		    }
		
		    if($wsnaw < $LastModified_unix){
			    // если сформированная время больше текущей, то отнимаем нужное время и генерируем дату так, как она была бы сгенерирована в то время
			    $wstest = $LastModified_unix - $wsuptimer;
			    $LastModified_unix = gmmktime(gmdate("H",$wstest), gmdate("d",$wstest), gmdate("d",$wstest)+gmdate("m",$wstest), gmdate("m",$wstest), gmdate("d",$wstest), gmdate("Y",$wstest));
		    }
		    if($wsnaw >= $LastModified_unix){
			    $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);
		    }
		
    }
    else {
	    $wstt = 'product';
    }

@aktaumag
Copy link
Author

aktaumag commented Jan 21, 2022

Если это хостинг nic.ru (RU-CENTER), то техподдержка не помогает даже для статических файлов, но можно перевести сервер в ручной режим управления и самому настроить конфигурацию Nginx.
Инструкция — https://www.nic.ru/help/nastrojka-sajta-kodirovka-perenapravlenie-logi-i-dr_6760.html#p6

Ищем в файле код:

 # Static files location
    location ~* ^.+\.(jpg|jpeg|gif|swf|png|ico|mp3|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|avi|ppt|txt|tar|mid|midi|wav|bmp|rtf|wmv|mpeg|mpg|mp4|m4a|spx|ogx|ogv|oga|webm|weba|ogg|tbz|js|7z|woff|svg|iso)$ {
        root   /home/login/domen.com/docs;
        access_log  /var/log/domen.com.access_log  combined;
        error_page 404 = @fallback;
        log_not_found off;
        accel_htaccess_switch on;
    }

Добавляем в список локации woff2 и прочие недостающие форматы
И добавляем туда if_modified_since before; и заодно expires 365d; для кеша в браузере.
Нужно чтоб получилось так:

 # Static files location
    location ~* ^.+\.(jpg|jpeg|gif|swf|png|avif|webp|ico|mp3|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|avi|ppt|txt|tar|mid|midi|wav|bmp|rtf|wmv|mpeg|mpg|mp4|m4a|spx|ogx|ogv|oga|webm|weba|ogg|tbz|js|7z|woff|woff2|ttf|svg|iso)$ {
        root   /home/login/domen.com/docs;
        access_log  /var/log/domen.com.access_log  combined;
        error_page 404 = @fallback;
        log_not_found off;
        accel_htaccess_switch on;
        if_modified_since before;
        expires 365d;
    }

Пример пути к файлу настроек:
/etc/nginx/vhosts/sites-enabled/site.ru.site.conf
/home/login/etc/nginx/site.ru.conf
/home/login/etc/nginx/sites-enabled/site.ru.site.conf

После внесения изменений в конфигурационные файлы Nginx достаточно перезапустить только Nginx, а не весь сервер.
Команда:
systemctl restart nginx

@aktaumag
Copy link
Author

Плагин для добавления заголовков к постам Wordpress: https://wordpress.org/plugins/last-modified-and-if-modified-since-headers/

@aktaumag
Copy link
Author

aktaumag commented May 16, 2023

Заметка

Чтобы в PHP получить заголовок запроса
в .htaccess прописываем правило

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteRule .* - [E=HTTP_IF_MODIFIED_SINCE:%{HTTP:If-Modified-Since}]
RewriteRule .* - [E=HTTP_IF_NONE_MATCH:%{HTTP:If-None-Match}]
</IfModule>

А потом уже в самом PHP получаем значения переданные в запросе и возвращаем либо сайт, либо 304 ответ
$_SERVER['HTTP_IF_MODIFIED_SINCE'] и $_SERVER['HTTP_IF_NONE_MATCH']

Примерный пример (чужой код)

function caching_headers ($file, $timestamp) {
    $gmt_mtime = gmdate('r', $timestamp);
    header('ETag: "'.md5($timestamp.$file).'"');
    header('Last-Modified: '.$gmt_mtime);
    header('Cache-Control: public');

    if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
        if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == $gmt_mtime || str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])) == md5($timestamp.$file)) {
            header('HTTP/1.1 304 Not Modified');
            exit();
        }
    }
}

caching_headers ($_SERVER['SCRIPT_FILENAME'], filemtime($_SERVER['SCRIPT_FILENAME']));

@aktaumag
Copy link
Author

aktaumag commented Jul 10, 2023

Письмо хостеру или сисадмину (переделанное).

Добрый день!
Домен: (указать домен)

Проверяю логотип: (ссылка на логотип)
На этом ресурсе: https://last-modified.com/ru/if-modified-since.html
Получаем ошибку: (скриншот)

Для исправления ситуации в конфигурации Nginx нужно прописать настройку: if_modified_since before; для всех статических файлов.

Должно получиться примерно так:

    # Static files location
    location ~* ^.+\.(jpg|jpeg|gif|swf|png|avif|webp|ico|mp3|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|avi|ppt|txt|tar|mid|midi|wav|bmp|rtf|wmv|mpeg|mpg|mp4|m4a|spx|ogx|ogv|oga|webm|weba|ogg|tbz|js|7z|woff|woff2|ttf|svg|iso)$ {
        # ... тут могут быть ещё и другие настройки для статических файлов
        if_modified_since before;
    }

Можете ли вы это сделать?
Или можете подсказать где/как я могу самостоятельно прописать эту настройку?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment