Bin*_*min 46 ajax jquery header http-status-code-304
如何检查jQuery.ajax()请求标头状态是否为"304 Not Modified"?
jqXHR.status通常返回200,即使请求的标题是"304 Not Modified".
ifModified:true 没有太多帮助,因为它破坏了XHR数据请求.
aps*_*ers 65
如果不手动处理缓存标头,则无法进行.通常,XHR API无法提供304个响应:
对于由用户代理生成的条件请求而导致的304 Not Modified响应,用户代理必须表现为服务器使用适当的内容给出200 OK响应.
jQuery通常不知道有304响应,因为浏览器告诉JavaScript有关网络上实际发生的事情的礼貌谎言.
但是有好消息(有点):你可以让Ajax产生304响应,但只能通过手动设置HTTP缓存头 If-Modified-Since或If-None-Match在请求中:
用户代理必须允许
setRequestHeader()通过设置请求标头(例如If-None-Match,If-Modified-Since)来覆盖自动缓存验证,在这种情况下,必须传递304 Not Modified响应.
因此,您可以使用以下代码:
var xhr = new XMLHttpRequest();
xhr.open("GET", "foo.html");
xhr.setRequestHeader("If-Modified-Since", "Fri, 15 Feb 2013 13:43:19 GMT");
xhr.send();
Run Code Online (Sandbox Code Playgroud)
一个基本的难点是你怎么知道最后修改日期或ETag要发送?浏览器具有用于发送请求的缓存信息,但不会与JavaScript共享该信息.幸运的是,jQuery跟踪Ajax响应中的头Last-Modified和ETag头,因此您可以使用ifModified:truejQuery在下次发送对该资源的请求时设置这些头值.
有两点需要注意:
304响应不携带数据.这是设计的.假设您已经选择使用缓存,那么您应该拥有缓存中已存在的数据副本!如果从服务器获取数据不成问题(即,因为您还没有这些数据),为什么要使用缓存?当您拥有旧数据并且只需要新数据时,应该使用缓存; 因此,用304取回数据应该不是问题.
jQuery必须具有最后修改日期或If-None-Match从先前请求存储的ETag(用于).过程如下:
第一次获取:jQuery没有缓存信息,所以它不发送If-Modified-Since或If-None-Match.当响应返回时,服务器可以宣布最后修改的数据或ETag,jQuery存储以供将来使用.
后续提取:jQuery具有上次提取的缓存信息,并将该数据转发到服务器.如果资源未更改,则Ajax请求将获得304响应.如果资源已更改,则Ajax请求将获得200响应,以及jQuery用于下次获取的新缓存信息.
但是,jQuery 不会在页面重新加载之间保留缓存信息(例如,在cookie中).因此,页面重新加载后第一次获取资源永远不会是304,因为jQuery没有要发送的缓存信息(即,我们重置回"第一次获取"情况).jQuery没有理由不能保留缓存信息,但目前它没有.
这里的底线是您可以使用缓存标头来获取JavaScript 304响应,但您无法访问浏览器自己的 ETag或特定资源的上次修改日期.因此,浏览器本身可能知道有关资源的缓存信息,但您的JavaScript代码却不知道.在这种情况下,浏览器将使用其缓存标头来获得真正的304响应,但转发对您的JavaScript代码的200响应,因为JavaScript没有发送任何缓存信息.
不可能使JavaScript 304请求与实际网络304响应完全对齐,因为浏览器已知的缓存信息和JavaScript代码已知的缓存信息可能以不可预测的方式不同.但是,在大多数情况下正确获取304个请求对于大多数实际开发需求来说已经足够了.
这是一个用Node.js编写的简短服务器示例(但它应该很简单,可以移植到其他语言):
require("http").createServer(function (req, res) {
console.log(req.headers["if-modified-since"]);
// always send Last-Modifed header
var lastModDate = "Fri, 13 Feb 2013 13:43:19 GMT";
res.setHeader("Last-Modified", lastModDate);
// if the request has a If-Modified-Since header,
// and it's newer than the last modification,
// then send a 304 response; otherwise send 200
if(req.headers["if-modified-since"] &&
Date.parse(lastModDate) <= Date.parse(req.headers["if-modified-since"])) {
console.log("304 -- browser has it cached");
res.writeHead(304, {'Content-Type': 'text/plain'});
res.end();
} else {
console.log("200 -- browser needs it fresh");
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('some content');
}
}).listen(8080);
Run Code Online (Sandbox Code Playgroud)
运行此服务器时,您可以在浏览器中加载页面并在浏览器控制台中执行两个不同的测试:
var xhr = new XMLHttpRequest();
xhr.open("GET", "/");
xhr.send();
xhr.onload = function() { console.log(xhr.status); }
Run Code Online (Sandbox Code Playgroud)
200即使浏览器提供If-Modified-Since请求标头并获得a 304(在浏览器看到服务器的Last-Modifed响应标头之后,所有请求将在第一个之后发生),此脚本将始终看到响应.
相比之下,这个脚本总会看到304响应:
var xhr = new XMLHttpRequest();
xhr.open("GET", "/");
xhr.setRequestHeader("If-Modified-Since", "Fri, 15 Feb 2013 13:43:19 GMT");
xhr.send();
xhr.onload = function() { console.log(xhr.status); }
Run Code Online (Sandbox Code Playgroud)
该脚本提供自己的If-Modified-Since请求标头(服务器上次修改日期后两天); 它不依赖于浏览器提供的任何内容If-Modified-Since,因此允许(根据XHR规范)查看304响应.
最后,这个脚本总会看到200:
var xhr = new XMLHttpRequest();
xhr.open("GET", "/");
xhr.setRequestHeader("If-Modified-Since", "Fri, 12 Feb 2013 13:43:19 GMT");
xhr.send();
xhr.onload = function() { console.log(xhr.status); }
Run Code Online (Sandbox Code Playgroud)
这是因为脚本使用的If-Modified-Since是服务器上次修改日期之前的内容,因此服务器始终发送一个200.服务器不会发送一个,304因为它假设客户端没有最新版本的缓存副本(即,客户端宣布自2月12日以来看到它发生了变化,但是在2月13日有一个变化,客户端显然还没见过).