如何测试"If-Modified-Since" HTTP头支持

12
使用PHP如何准确地测试远程网站是否支持“If-Modified-Since” HTTP头。根据我所读的,如果您获取的远程文件自请求标头指定日期以来已被修改,则应返回200 OK状态。 如果它没有被修改,则应返回304未修改状态。 因此,我的问题是,如果服务器不支持“If-Modified-Since”,但仍返回200 OK怎么办?有一些工具可以检查您的网站是否支持“If-Modified-Since”,所以我想知道它们是如何工作的。编辑:我使用Curl进行了一些测试,发送了以下内容;
curl_setopt($ch, CURLOPT_HTTPHEADER, array("If-Modified-Since: ".gmdate('D, d M Y H:i:s \G\M\T',time()+60*60*60*60)));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_FORBID_REUSE, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4);
curl_setopt($ch, CURLOPT_TIMEOUT, 4);

即一个未来日期的google.com返回;
HTTP/1.0 304 Not Modified
Date: Fri, 05 Feb 2010 16:11:54 GMT
Server: gws
X-XSS-Protection: 0
X-Cache: MISS from .
Via: 1.0 .:80 (squid)
Connection: close

如果我发送;

curl_setopt($ch, CURLOPT_HTTPHEADER, array("If-Modified-Since: ".gmdate('D, d M Y H:i:s \G\M\T',time()-60*60*60*60)));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_FORBID_REUSE, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4);
curl_setopt($ch, CURLOPT_TIMEOUT, 4);

即,如果输入过去的日期,google.com 将返回:
HTTP/1.0 200 OK
Date: Fri, 05 Feb 2010 16:09:12 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
Server: gws
X-XSS-Protection: 0
X-Cache: MISS from .
Via: 1.0 .:80 (squid)
Connection: close

如果我将两者发送到不支持此功能的bbc.co.uk;
未来的那个会返回;
HTTP/1.1 200 OK
Date: Fri, 05 Feb 2010 16:12:51 GMT
Server: Apache
Set-Cookie: BBC-UID=84bb66bc648318e367bdca3ad1d48cf627005b54f090f211a2182074b4ed92c40ForbSoft%20Web%20Diagnostics%20%28URL%20Validator%29; expires=Tue, 04-Feb-14 16:12:51 GMT; path=/; domain=bbc.co.uk;
Accept-Ranges: bytes
Cache-Control: max-age=0
Expires: Fri, 05 Feb 2010 16:12:51 GMT
Pragma: no-cache
Content-Length: 111677
Content-Type: text/html

过去的日期返回;
HTTP/1.1 200 OK
Date: Fri, 05 Feb 2010 16:14:01 GMT
Server: Apache
Set-Cookie: BBC-UID=841b66ec44232cd91e81e88a014a3c5e50ed4e20c0e07174c4ff59675cd2fa210ForbSoft%20Web%20Diagnostics%20%28URL%20Validator%29; expires=Tue, 04-Feb-14 16:14:01 GMT; path=/; domain=bbc.co.uk;
Accept-Ranges: bytes
Cache-Control: max-age=0
Expires: Fri, 05 Feb 2010 16:14:01 GMT
Pragma: no-cache
Content-Length: 111672
Content-Type: text/html

所以我的问题仍然存在。

请发布您正在使用的curl命令,我正在测试命令行,无论我发送什么标头,都只得到200s。 - adamJLev
如果服务器不支持 If-Modified-Since 但仍返回200状态码,则与您发送没有 If-Modified-Since 的请求相同,服务器将以200状态码响应。没有区别。200就是200,“请求成功”。 - Gumbo
@Infinity - 我已经在我的原始帖子中添加了curl命令/选项。 - J.C
1
这个问题本身就是错误的,因为请求的位置/实体必须支持此头部,而不是网站或服务器(正如@Infinity所指出的)。因此,测试单个URL并不能告诉您有关服务器的其余可请求实体的任何信息。 - hurikhan77
3个回答

8
我对此进行了一些测试,结果如下:
如果您发送一个带有过去日期的If-Modified-Since标头(5分钟前的时间应该就可以了),那么Google.com、W3.org和Mattcutts.com等网站将返回“HTTP/1.1 304 Not Modified”标头。而Yahoo.com、BBC.co.uk和Stackoverflow.com等网站则始终返回“HTTP/1.1 200 OK”。
“Last-Modified”标头与“If-Modified-Since”没有任何关系,因为发送“HTTP/1.1 304 Not Modified”标头的整个目的是不必随之发送主体(从而节省带宽-这正是其背后的全部意义)。
因此,我的问题的答案是:如果一个网站在您发送一个“5分钟前的If-Modified-Since”标头时没有返回“HTTP/1.1 304 Not Modified”标头,则该网站不正确地支持“If-Modified-Since”请求。
如果我说错了,请告诉我并提供测试以证明。
编辑:我忘了添加一个好的测试方法,即向域名(例如w3.org)发出一个普通的HEAD请求,获取“Last Modified”日期,然后再使用“If-Modified-Since:”发出另一个请求。这将测试“Last Modified”值和“If-Modified-Since”请求是否都得到支持。请注意:仅因为服务器发送回一个“Last Modified”日期并不意味着它支持“If-Modified-Since”。

我很高兴你找到了解决方案,但是在我的答案中,我提到这是一种更“实用”的方式来推断服务器的能力,而不是更“理论”的头部方法。引用我的话:“也许您只需执行两个请求,一个跟随另一个发送If-Modified-Since头,然后验证第二个请求是304还是200。” - adamJLev
@Infinity - 如果你看了我的回答,你会发现你的想法有些不同,但我能理解你所说的“实际”方法,这也是我最终采取的方法。 - J.C
首先,每个浏览器对此概念的处理方式是不同的。其次,使用 Chrome v22,服务器必须发送一个 "Last-Modified" 头部信息,以便 Chrome 发送后续的 "If-Modified-Since" 头部信息。这个回答是不正确的。 - Matty F

5
如果实体返回“Last-Modified”标头,则支持它。这很有道理。
更多信息:http://httpd.apache.org/docs/2.2/caching.html(有关条件请求的简要指南)
显然,只有静态页面/文件才会具有该标头。对于动态内容(asp、php等),无法通过标头知道(除非站点处理程序手动缓存,例如like this),根据我的经验,实体可能支持或不支持If-Modified-Since。
也许您可以只做两个请求,一个跟随另一个,发送If-Modified-Since标头,然后验证第二个请求是304还是200。
编辑-hurikhan77指出了一个重要的注意事项,即例如测试此功能的站点根目录并不能保证站点的其余部分是否也支持此功能。

是的,这很有意义,非常感谢您发送给我的链接。 - J.C
这并不完全正确:将“服务器”替换为“实体”,它就会适合。 - hurikhan77

1
关于上面的第一个答案,我想指出条件请求在动态内容和静态内容上同样有意义。如果生成动态内容的代码知道后端实体(例如数据库项)没有更改,它应该在条件请求时发送304。
Jan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接