qnixnet
@qnixnet

Как подружить Nginx fastcgi_cache и Last-Modified (HTTP ответ 304)?

Помогите подружить Nginx fastcgi_cache и ответ HTTP заголовка Last-Modified
По отдельности они работают прекрасно, но когда их попробовать объединить то, ответ от сайта, о том что статья имеет изменения не уходит, в ответе сервера видно дату последнего изменения поста, но не срабатывает IF_MODIFIED_SINCE и в итоге роботам поисковиком не приходит ответ 304, что на странице не было изменений и они по новому выгружают весть контент, что бы сравнить изменения.

Моя настройка Nginx:
/etc/nginx/nginx.conf
. . .
http {
        # Basic Settings
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        server_tokens off;
        client_max_body_size 64m;
        server_names_hash_bucket_size 64;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
. . .
        # Gzip Settings
        gzip on;
        gzip_proxied any;
        gzip_comp_level 5;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
        gzip_disable "msie6";
. . .
        # Cache Settings
        fastcgi_cache_path /var/cache/nginx levels= use_temp_path=off keys_zone=cgicache:100m inactive=1d max_size=1g;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";
}


/etc/nginx/sites-available/mysite
server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name mysite;
        root /var/www/mysite;
        index index.php index.html index.htm;
. . .
        set $skip_cache 0;
        if ($request_method = POST) {
                set $skip_cache 1;
        }
        if ($query_string != "") {
                set $skip_cache 1;
        }
        if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
                set $skip_cache 1;
        }
        if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
                set $skip_cache 1;
        }

        rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.xml$ "/index.php?xml_sitemap=params=$2" last;
        rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.xml\.gz$ "/index.php?xml_sitemap=params=$2;zip=true" last;
        rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.html$ "/index.php?xml_sitemap=params=$2;html=true" last;
        rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.html.gz$ "/index.php?xml_sitemap=params=$2;html=true;zip=true" last;

        location ~ \.php$ {
                ssi off;
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
                fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
                fastcgi_cache_bypass $skip_cache;
                fastcgi_no_cache $skip_cache;
                fastcgi_cache cgicache;
                fastcgi_cache_valid 200 301 302 1d;
                fastcgi_cache_valid 404 1m;
                fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
                fastcgi_cache_min_uses 1;
                fastcgi_cache_lock on;
                add_header CGI_Cache $upstream_cache_status;
        }

        location = /robots.txt { log_not_found off; access_log off; allow all; }
        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; }
        location ~ /\.ht { deny all; }
        . . .
}


За основу работы HTTP заголовка Last-Modified был взят код из сайта
Здесь все просто, подключил сниппет и все работает:
function Sheensay_HTTP_Headers_Last_Modified() {
	if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || ( is_admin() ) ) { return; }
	$last_modified = '';

	// Для страниц и записей
	if ( is_singular() ) {
		global $post;

		// Если пост запаролен - пропускаем его
		if ( post_password_required( $post ) ) return;
		if ( !isset( $post -> post_modified_gmt ) ) { return; }
		$post_time = strtotime( $post -> post_modified_gmt );
		$modified_time = $post_time;

		// Если есть комментарий, обновляем дату
		if ( ( int ) $post -> comment_count > 0 ) {
			$comments = get_comments( array(
				'post_id' => $post -> ID,
				'number' => '1',
				'status' => 'approve',
				'orderby' => 'comment_date_gmt',
			));

			if ( !empty( $comments ) && isset( $comments[0] ) ) {
				$comment_time = strtotime( $comments[0] -> comment_date_gmt );
				if ( $comment_time > $post_time ) { $modified_time = $comment_time; }
			}
		}
		$last_modified = str_replace( '+0000', 'GMT', gmdate( 'r', $modified_time ) );
	}

	// Cтраницы архивов: рубрики, метки, даты и тому подобное
	if ( is_archive() || is_home() ) {
		global $posts;
		if ( empty( $posts ) ) { return; }
		$post = $posts[0];
		if ( !isset( $post -> post_modified_gmt ) ) { return; }
		$post_time = strtotime( $post -> post_modified_gmt );
		$modified_time = $post_time;
		$last_modified = str_replace( '+0000', 'GMT', gmdate( 'r', $modified_time ) );
	}

	// Если заголовки уже отправлены - ничего не делаем
	if ( headers_sent() ) { return; }

	if ( !empty( $last_modified ) ) {
		header( 'Last-Modified: ' . $last_modified );
		if ( !is_user_logged_in() ) {
			if ( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) && strtotime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) >= $modified_time ) {
				header( $_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified' );
			}
		}
	}
}
add_action( 'template_redirect', 'Sheensay_HTTP_Headers_Last_Modified' );


Если отключить кэширование Nginx, то плагин работает корректно и на выходе я получаю ответ 304. Проверял этим сервисом. Но когда включено кэшированние, то сервис не отдает 304 ответ и тест проходит неуспешно:
Результат: провалено
Сайт отдал время последней модификации, но не отреагировал на If-Modified-Since.

Возможно их как то "подружить"?
  • Вопрос задан
  • 35 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Artezio Москва
от 130 000 до 250 000 ₽
от 60 000 до 120 000 ₽
30 нояб. 2020, в 13:43
1000 руб./за проект
30 нояб. 2020, в 12:38
1000 руб./за проект