【问题标题】:Image proxy caching problems - wrong headers?图像代理缓存问题 - 错误的标头?
【发布时间】:2015-01-26 10:18:26
【问题描述】:

我的网站上有一个代理脚本,用于缩小图像(也将它们保存在本地缓存文件夹中)并将它们与 Etag、缓存标头等一起发送给用户。

但是,当您访问该页面时,您可以清楚地看到图像加载缓慢,即使您关闭选项卡并再次进入该页面 - 显然它们应该在缓存中(或者也许我的连接很糟糕,但我看到它们甚至重新加载在 64 MB/s 连接上)

你可以在这里看到图片,标题照片:http://www.ondrovo.com/

我怀疑我以某种方式发送了错误的标头,我不太确定。

这是我的图像传递函数(有点缩短):

/** Send file to user */
public static function send($file)
{
    // ETAG
    $last_modified_time = filemtime($file);
    $etag = md5_file($file);

    header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT");
    header("Etag: $etag");
    header('Expires: pageload + 168 hours');
    header('Cache-Control: public, max-age=604800, must-revalidate');

    // exit if not modified
    if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time ||
        @trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
        header("HTTP/1.1 304 Not Modified");
        exit;
    }

    $mimetype = self::getMime($path);
    if(in_array($mimetype, ['image/jpeg', 'image/png', 'image/pjpeg'])) {
        // it's an image
        if(isset($_GET['w']) || isset($_GET['h'])) {
            // resize, save to cache folder
            // $tmp_fname holds the path to the resized image
            $file = $tmp_fname;
        }
    }

    header('Content-Type: ' . $mimetype);
    header('Content-Length: ' . filesize($file));

    readfile($file);
    flush();
    exit;
}

另外,这里有一个标头转储,如果有帮助的话

请求

GET /about/header.jpg?h=92&w=92 HTTP/1.1
Host: www.ondrovo.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
Referer: http://www.ondrovo.com/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: cs,en-US;q=0.8,en;q=0.6
Cookie: PHPSESSID=64e177be06a1b7bb665dd756151d014f

回应

HTTP/1.1 200 OK
Date: Thu, 27 Nov 2014 18:31:57 GMT
Server: Apache
Expires: pageload + 168 hours
Cache-Control: public, max-age=604800, must-revalidate
Last-Modified: Fri, 07 Nov 2014 14:39:09 GMT
ETag: b38a22993d1fb1ee17905067340596e4
Content-Length: 2268
Content-Type: image/jpeg
Via: 1.1 vhost.phx6.nearlyfreespeech.net:3128 (squid/2.7.STABLE7)

如果我的标题没问题的话,有人能帮我检查一下吗?

另外,图像通过 GET 参数获取大小可能是个问题吗?

【问题讨论】:

  • 确认 strtotime() 实际上正在正确转换您的标头时间戳。永远不要依赖它做“正确的事”。这很好,但它不是万无一失的,也绝对不是无所不知的。

标签: php http caching


【解决方案1】:

首先,您的标题Expires: pageload + 168 hours 不符合正确的语法。它应该是一个时间戳。

5.3。过期

“过期”标题字段给出了日期/时间,之后
响应被认为是陈旧的。进一步讨论见第 4.2 节 新鲜度模型。

Expires 字段的存在并不意味着原来的
资源将在此之前、之前或之后更改或停止存在
时间。

Expires 值是 HTTP 日期时间戳,如第 1 节中所定义 [RFC7231] 的 7.1.1.1。

 Expires = HTTP-date

例如

 Expires: Thu, 01 Dec 1994 16:00:00 GMT

缓存接收者必须解释无效的日期格式,尤其是 值“0”,表示过去的时间(即“已经
过期”)。

rfc 7234, section 5.3

但是,Cache-Control 标头应该为客户端覆盖它。

您使用什么客户端进行跟踪?看起来它被明确要求重新加载整个页面,无论是因为

编译指示:无缓存 缓存控制:无缓存 (要求 squid 服务器不提供缓存内容)

并且缺少表明客户端已经缓存了资源的标头(If-None-Match、If-Modified-Since)。

请注意,如果以私密/隐身模式访问网站,根据功能的实现,浏览器可能不会缓存任何资源。

【讨论】:

  • 看起来更正过期标签实际上很有帮助。此外,我发现我的图像大小调整脚本没有使用 png 压缩,因此这甚至可能会影响本地缓存的加载时间。从 64kB 图像轻松制作 1MB。
猜你喜欢
  • 2011-09-01
  • 2012-04-26
  • 2011-10-28
  • 1970-01-01
  • 2020-01-18
  • 2012-02-05
  • 2011-09-22
  • 1970-01-01
  • 2013-09-15
相关资源
最近更新 更多