使用PHP-cURL解决Gravatar跳转i2.wp.com问题

Gravatar为我们提供了十分便利的头像服务,美中不足的一点就是因为众所周知的原因这项服务的速度不甚理想。我们已经有了自建镜像站这样不错的解决方案,但是我由于没有接入也暂时不想接入支持此类服务的CDN,只能选取现有的访问速度稍理想的源。但是这样一来就又存在一个问题:返回自定义默认头像时,会302到i2.wp.com(大概是出于防止恶意代码的缘故),而这个过程速度极不理想,一方面,i2.wp.com需要读取我定义的默认头像文件,另一方面,i2.wp.com访问速度糟糕透顶。于是,优化这一过程成为了当务之急。这里我使用了PHP的cURL库来达到这个目的。

为什么一定要用PHP-cURL

前面已经说过,我暂时没有办法自建Gravatar镜像站,所以只能通过避免跳转想想办法。十分遗憾,JavaScript无法处理302状态码,也就是客户端脚本没办法帮我们解决了,我们只能从服务端想想办法。目前看来最为有效的方法就是使用PHP-cURL了。

完整方案

我的博客请求Gravatar服务时会先发送用户的邮箱到我的服务器,由服务器脚本合成一个Gravatar的url再返回给前端,直接操作这个过程就可以了。合成url后并不直接返回,而是用cURL请求一次,如果状态码是302则返回我设定好的默认头像地址,否则返回合成的url。

进一步考虑优化效率,这次cURL中我们只关心响应头,准确地说,是响应头中的状态码,所以响应正文我们全部可以不要,这一点可以通过设置CURLOPT_NOBODYtrue来实现,即采用HEAD请求方式。考虑到响应正文是一张图片,这里的速度优化是很明显的。

    public static function getGravator($email,$host,$size){
        $options = mget();
        $default = '';
        if (strlen($options->defaultAvator) > 0){
            $default = $options->defaultAvator;
        }
        $url = '/';//自定义头像目录,一般保持默认即可
        //$size = '40';//自定义头像大小
        $rating = Helper::options()->commentsAvatarRating;
        $hash = md5(strtolower($email));
        $avatar = $host . $url . $hash . '?s=' . $size . '&r=' . $rating . '&d=' . $default;
        $testCurl = curl_init();
        curl_setopt($testCurl, CURLOPT_URL, $avatar);
        curl_setopt($testCurl, CURLOPT_HEADER, true);
        curl_setopt($testCurl, CURLOPT_NOBODY, true);
        curl_setopt($testCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($testCurl, CURLOPT_POST, false);
        curl_setopt($testCurl, CURLOPT_FOLLOWLOCATION, false);
        curl_setopt($testCurl, CURLOPT_CONNECTTIMEOUT, 1);
        curl_setopt($testCurl, CURLOPT_TIMEOUT, 1);
        curl_exec($testCurl);
        if(curl_getinfo($testCurl, CURLINFO_HTTP_CODE) != 200) $avatar = $default;
        return $avatar;
    }

保险起见,我还设置了超时为1秒,且状态码不为200就返回默认。

这样一来,默认头像的加载就不再会被i2.wp.com进行中转了。

最后修改:2019 年 11 月 03 日 09 : 21 PM
欢迎投食喵 ~

发表评论 取消回复

6 条评论

  1. 皮皮凛

    emmmmmmm...感觉不是很有必要...还需要服务器先请求一次判断是否有头像....难道不是拖慢了速度么

    1. 无限UCW
      @皮皮凛

      根据均摊分析和实际测试,在客户端 GET 请求 i2.wp.com 响应慢,而服务端 HEAD 请求响应快,并加上 cache 时,对访问默认头像的情况有较大速度提升。

      1. 皮皮凛
        @无限UCW

        但是有头像(非默认头像)时服务端也会请求一次。有QQ邮箱解析QQ头像,出现无头像需要展示默认头像的机会实在不多。

        1. 无限UCW
          @皮皮凛

          哈,这个怎么说呢,Gravatar 毕竟还是没有完全普及,QQ 邮箱的解析也并没有被 handle,对于我个人来说,我目前挂网站的机子 HEAD 请求一次是非常快的,响应速度可以保证一般情况下在 0.5 s 内,而我的 cache 规则(上面没有提到),是对每个邮箱,最多只进行一次请求,后续展现的时候是直接本地的文件 IO,可以忽略不计,这才是我目前形成的我自己可以接受的解决方案。

          1. 皮皮凛
            @无限UCW

            确实

  2. 寒夜方舟

    我的头像太大貌似挂了