HTTP缓存:为什么在假定缓存文件是最新的之前,浏览器根本没有检查服务器? [英] HTTP caching: why is browser not checking server at all before presuming cached file is current?

查看:167
本文介绍了HTTP缓存:为什么在假定缓存文件是最新的之前,浏览器根本没有检查服务器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是关于我继承的一些代码;目的很明确,但是(至少在Firefox和Chrome中)它的行为并不像预期那样。



这个想法显然是建立一个基于客户端数据的PNG并将其缓存,除非并且直到数据更改。可能的原因是,无论客户端是否使用cookie,本地存储等,都保留PNG的状态,但同时服务器不保留有关此客户端的数据。



客户端JavaScript:

 函数read_or_write_png(name,value){
// WRITE如果定义了值,非空等,否则返回
if(value){
//写入

//使用cookie传递新数据到服务器
document.cookie ='bx_png ='+ value +';路径= /;

// bx_png.php根据http cookie生成映像
//并返回它缓存的
var img = new Image();
img.style.visibility ='hidden';
img.style.position ='绝对';
img.src ='bx_png.php?name ='+ name; //魔术说加载这个。
//'name'不会被咨询服务器端,
//这里只是为了得到唯一性
//用于缓存的内容。
} else {
// READ

//杀掉cookie让服务器发送一个304头文件
document.cookie ='bx_png =;到期= 2010年9月20日星期一00:00:00 UTC;路径= /;

//载入缓存的.png
var img = new Image();
img.style.visibility ='hidden';
img.style.position ='绝对';
img.src ='bx_png.php?name ='+ name;


bx_png.php中的服务器端PHP: p>

  if(!array_key_exists('bx_png',$ _COOKIE)||!isset($ _ COOKIE ['bx_png'])){
//我们没有cookie。客户端代码是故意的。强制缓存。
header(HTTP / 1.1 304 Not Modified);
} else {
header('Content-Type:image / png');
header('Last-Modified:Wed,30 Jun 2010 21:36:48 GMT');
header('Expires:Tue,20 Dec Dec 20:30 23:30:45 GMT');
header('Cache-Control:private,max-age = 630720000');
//后面跟着PNG的内容
}

这工作正常第一次写入PNG并缓存它,但显然它的意图是能够再次调用它,为相同的名称传递不同的值,并且缓存 。实际上,一旦PNG被缓存,它就会(通过Fiddler)显示服务器根本没有被调用。也就是说,在试图读取时,浏览器不会去服务器并返回304,而是从缓存中获取内容,而无需与服务器通信。这部分本身是无害的,但当然有害的是同样的事情发生在尝试写入时,并且服务器从来没有机会根据新值返回不同的PNG。



有没有人有任何想法如何调整这个来实现其明显的意图?也许在标题中有点不同?也许某种方式从客户端清除缓存?也许完全是我还没有想到的其他东西?就服务器端和客户端而言,我是一位非常扎实的开发人员,但是对HTTP协议等技巧的熟练程度较低。

解决方案

您需要在 Cache-Control 标头中添加 must-revalidate 以告诉浏览器来做到这一点。


This is about some code I inherited; the intent is clear, but (at least in Firefox and Chrome) it is not behaving as intended.

The idea is clearly to build a PNG based on client-side data and to cache it unless and until that data changes. The intent presumably is that the state of the PNG is preserved regardless of whether or not the client is using cookies, local storage, etc., but at the same time the server does not preserve data about this client.

Client-side JavaScript:

function read_or_write_png(name, value) {
    // WRITE if value is defined, non-null, etc., get otherwise
    if (value) {
        // WRITE

        // Use cookie to convey new data to server
        document.cookie = 'bx_png=' + value + '; path=/';        

        // bx_png.php generates the image
        // based off of the http cookie and returns it cached
        var img = new Image();
        img.style.visibility = 'hidden';
        img.style.position = 'absolute';
        img.src = 'bx_png.php?name=' + name; // the magic saying "load this".
                                             // 'name' is not consulted server-side,
                                             //  it's here just to get uniqueness
                                             //  for what is cached.
    } else {
        // READ

        // Kill cookie so server should send a 304 header
        document.cookie = 'bx_png=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';

        // load the cached .png
        var img = new Image();
        img.style.visibility = 'hidden';
        img.style.position = 'absolute';
        img.src = 'bx_png.php?name=' + name;            
    }
}

Server-side PHP in bx_png.php:

if (!array_key_exists('bx_png', $_COOKIE) || !isset($_COOKIE['bx_png'])) {
    // we don't have a cookie. Client side code does this on purpose. Force cache.
    header("HTTP/1.1 304 Not Modified");
} else {
    header('Content-Type: image/png');
    header('Last-Modified: Wed, 30 Jun 2010 21:36:48 GMT');
    header('Expires: Tue, 31 Dec 2030 23:30:45 GMT');
    header('Cache-Control: private, max-age=630720000');
    // followed by the content of the PNG        
}

This works fine to write the PNG the first time and cache it, but clearly the intention is to be able to call this again, pass a different value for the same name, and have that cached. In practice, once the PNG has been cached, it would appear (via Fiddler) that the server is not called at all. That is, on an attempted read, rather than go to the server and get a 304 back, the browser just takes the content from the cache without ever talking to the server. In and of itself, that part is harmless, but of course what is harmful is that the same thing happens on an attempted write, and the server never has a chance to send back a distinct PNG based on the new value.

Does anyone have any idea how to tweak this to fulfill its apparent intention? Maybe something a bit different in the headers? Maybe some way of clearing the cache from client-side? Maybe something else entirely that I haven't thought of? I'm a very solid developer in terms of both server-side and client-side, but less experienced with trickiness like this around the HTTP protocol as such.

解决方案

You need to add must-revalidate to your Cache-Control header to tell the browser to do that.

这篇关于HTTP缓存:为什么在假定缓存文件是最新的之前,浏览器根本没有检查服务器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆