大家都知道200是正常,304是没有变化、没有修改。
但200是不是真的就“正常”,304背后又都做了什么?他是怎么判断没修改的?

200(From cache)是直接点击链接访问,输入网址按回车访问触发(这两种情况都不会有Etag);
304(Not Modified)是刷新页面时触发,或是设置了长缓存、或当Etag没有移除时触发。

先说说304
当你第一次请求一个资源的时候,server会同时生成并返回一个字符串在响应头里,叫Etag。
浏览器接到资源后,缓存资源的同时也会把这个Etag保存下来,成为If-None_Match 。Etag可以看作是一个资源的唯一标识,当你第二次请求这个资源的时候,请求头里会带着这个Etag,server会拿server该资源现在的Etag跟请求头中的If-None_Match做对比,然后看看If-Modified-Since过没过期,如果一样,直接告诉他:你就用本地的吧,我没变,就不给你返回了。所以返回了304,304就是这样。

再说说200 From Cache
这个虽然是200,但他根本就没有跟server做交互,直接拉的本地缓存。
上边已经说了From Cache的触发条件,但如果想一直持续From Cache不想304怎么办?
可以在Server端配置移除Etag,具体请听下回分解.

扩展:
想让浏览器缓存住php页面,为什么$_SERVER['HTTP_IF_MODIFIED_SINCE']为空?使用的nginx。

<?php
date_default_timezone_set('PRC');//时区设置 设置为 中国第八区时间
date_default_timezone_set ( "Asia/Shanghai" );

// 这里加@可以防止出错提示
$modified_time = @$_SERVER['HTTP_IF_MODIFIED_SINCE'];
echo $modified_time;
if (strtotime($modified_time) + 3600 > time()) 
{
    header("http/1.1 304");
    exit(0);
}
header("Last-Modified:".gmdate("D, d M Y H:i:s")." GMT");
header("Expires:".gmdate("D, d M Y H:i:s",time()+3600)." GMT");
header("Cache-Control: max-age=3600");
echo 'test';
echo "<br/>";

$time = date("Y-m-d H:i:s");
echo $time;

?>

clipboard.png

clipboard.png

If-Modified-Since是服务器进行判断,而非cgi程序判断,另外If-Modified-Since是上次服务器返回头部中的Last-Modified信息,如果返回的头部中没有Last-Modified,则请求时是不会带上,也就是说Last-Modified / If-Modified-Since是成对使用的。

什么是”Last-Modified”?
  在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,格式类似这样:
  Last-Modified: Fri, 12 May 2006 18:53:33 GMT
  客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过:
  If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
  如果服务器端的资源没有变化,则自动返回 HTTP 304 (Not Changed.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。

如果你真的想知道If-Modified-Since的内容,需要在nginx中fastcgi.conf配置

// 请求的头部的所有内容
fastcgi_param  REQUEST_HEADER     $request;

原文地址:
HTTP 304(Not Modified)和200(From Cache)的区别
什么是”Last-Modified”?


Corwien
6.3k 声望1.6k 粉丝

为者常成,行者常至。