WordPress缓存Gravatar头像失败与排查

发布于 2021-04-11  75 次阅读


众所周知的原因,Gravatar 头像服务被墙,国内无法访问,导致 WordPress 的网站打开加载很久都加载不出来,大大降低体验,看着不爽,于是我在网上找到一个比较可行的方案——缓存到本地,代码如下,加入到主题的 functions.php 文件。

缓存 Gravatar 头像到本地服务器

//缓存 Gravatar 头像
function memory_cache_avatar($avatar) {
	if(!is_dir('avatar'))//判断是否有缓存目录
		mkdir('avatar', 0755, true);//否,则创建头像缓存目录
	$tmp = strpos($avatar, 'https');
	$g = substr($avatar, $tmp, strpos($avatar, "'", $tmp) - $tmp);
	$tmp = strpos($g, 'avatar/') + 7;
	$f = substr($g, $tmp, strpos($g, "?", $tmp) - $tmp);
	$w = home_url();
	list($width,$height,$type,$attr) = getimagesize($g);//获取头像参数
	$e = ABSPATH .'avatar/'. $f .'-'.$width.'.jpg';
	$t = 604800; //设定 7 天, 单位:秒
	//if ( empty($default) ) $default = 'https://www.gal.moe/content/images/users/ndT/av_1617594828.jpg';
	if ( !is_file($e) || (time() - filemtime($e)) > $t ){ //当头像不存在或者文件超过 7 天才更新
		copy(htmlspecialchars_decode($g), $e);
	}else{
		$avatar = strtr($avatar, array($g => $w.'/avatar/'.$f.'-'.$width.'.jpg'));
	}
	if (filesize($e) < 500) copy($default, $e);
	return $avatar;
}
add_filter('get_avatar', 'memory_cache_avatar');

失败与排查

使用后却发现 WordPress 缓存 Gravatar 头像失败,发现打开头像的网址返回404,经过长时间排查终于发现原来是因为使用了网上流行的 Nginx 多站点模式伪静态规则导致。

#多站点模式伪静态
rewrite ^/([_0-9a-zA-Z-]+/)?wp-admin$ /$1wp-admin/ permanent;
if (-f $request_filename){
    set $rule_2 1;
}
if (-d $request_filename){
    set $rule_2 1;
}
if ($rule_2 = "1"){
#ignored: “-” thing used or unknown variable in regex/rew
}
rewrite ^/([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) /$2 last;
rewrite ^/([_0-9a-zA-Z-]+/)?(.*.php)$ /$2 last;
rewrite /. /index.php last;

删除了 Nginx 伪静态规则后返回的头像网址可以正常访问打开了,但奇怪的是在网页上还是加载不出来,再继续浪费时间排查发现原来是使用了 WordPress 的 Jetpack 插件,打开了“为图像启用延迟加载功能”导致的……这实在是……太倒霉了!!

关闭这个功能后终于可以正常显示。

但又发现部分主题还是显示有问题的,缓存头像并没有产生作用的样子,虽然实际上是已经正常执行了,应该是那些主题或者调用的一些插件使用的头像加载函数是自作聪明搞了一个自定义的出来,非标准常规使用的方式导致的。

update 2021-04-12

在移动端访问时发现头像又无法显示了,排查发现新版本的 WordPress 会自作聪明地给图片加 srcset 属性,所谓的自适应图片属性,在移动端上该属性作用生效,所以又默认加载了 Gravatar 的图片源,导致无法显示。

又在网上查了很多资料,结合各种复制粘贴的信息,总的来说解决办法就是需要加入以下代码到主题的 functions.php 文件禁用此功能才行。

// disable srcset on frontend
function disable_wp_responsive_images() {
	return 1;
}
add_filter('max_srcset_image_width', 'disable_wp_responsive_images');
// disable 768px image generation
function disable_wp_responsive_image_sizes($sizes) {
	unset($sizes['medium_large']);
	return $sizes;
}
add_filter('intermediate_image_sizes_advanced', 'disable_wp_responsive_image_sizes');

然而……

并没有什么卵用!!!!!!!!!

完全一丁点作用都没有好不!?

于是我动用谷歌搜索引擎,不断改变改变关键词又在网上搜了一遍又一遍,终于……结合网上查的类似内容,结合我自己的实际修改情况,我将缓存 Gravatar 头像到本地服务器的代码改成这样,完美解决:

//缓存 Gravatar 头像
function memory_cache_avatar($avatar) {
	if(!is_dir('avatar'))//判断是否有缓存目录
		mkdir('avatar', 0755, true);//否,则创建头像缓存目录
	$tmp = strpos($avatar, 'https');
	$g = substr($avatar, $tmp, strpos($avatar, "'", $tmp) - $tmp);
	$tmp = strpos($g, 'avatar/') + 7;
	$f = substr($g, $tmp, strpos($g, "?", $tmp) - $tmp);
	$w = home_url();
	list($width,$height,$type,$attr) = getimagesize($g);//获取头像参数
	$e = ABSPATH .'avatar/'. $f .'-'.$width.'.jpg';
	$t = 604800; //设定 7 天, 单位:秒
	//if ( empty($default) ) $default = 'https://www.gal.moe/content/images/users/ndT/av_1617594828.jpg';
	if ( !is_file($e) || (time() - filemtime($e)) > $t ){ //当头像不存在或者文件超过 7 天才更新
		copy(htmlspecialchars_decode($g), $e);
	}else{
		$avatar = strtr($avatar, array($g => $w.'/avatar/'.$f.'-'.$width.'.jpg'));
	}
	if (filesize($e) < 500) copy($default, $e);
	// 替换 Gravatar 头像连接为本地
	$avatar = str_replace(array("www.gravatar.com", "0.gravatar.com", "1.gravatar.com", "2.gravatar.com","secure.gravatar.com"), "no.gal.moe", $avatar);
	$avatar = preg_replace(array('/srcset=(\'|")(.*)(\'|")/isU'),array(''),$avatar);
	return $avatar;
}
add_filter('get_avatar', 'memory_cache_avatar');

主要是增加了两句代码:

// 替换 Gravatar 头像连接为本地
	$avatar = str_replace(array("www.gravatar.com", "0.gravatar.com", "1.gravatar.com", "2.gravatar.com","secure.gravatar.com"), "no.gal.moe", $avatar);
	$avatar = preg_replace(array('/srcset=(\'|")(.*)(\'|")/isU'),array(''),$avatar);

起主要作用的应该是第二行代码,第一行是保险起见,怕替换的不够彻底。

我去,排查这些非自己专业领域的问题真的非常费时间!花费了这么长的时间才解决这一个小小的问题!

我只能说,这 WordPress 果真如我当初开发 RewrZ 项目时所吐槽的那样——臃肿,特别多不想要的功能,想要的功能反而很多没有,要不断地找插件补充,或者需要自行修改。