HTTP的请求头标签 If-Modified-Since

HTTP的请求头标签 If-Modified-Since

一直以来没有留意过HTTP请求头的IMS(If-Modified-Since)标签。

最近在分析Squid的access.log日志文件时,发现了一个现象。
就是即使是对同一个文件进行HTTP请求,第一次和第二次产生的网络流量数据也是不一致的。

在调查的过程中,逐渐了解了HTTP的If-Modified-Since的头标签的作用。

大家都知道客户端浏览器是有缓存的,里面存放之前访问过的一些网页文件。
例如IE,会把缓存文件存到“C:\Documents and Settings\zh2000g\Local Settings\Temporary Internet Files”
这样类似的目录里。
其实缓存里存储的不只是网页文件,还有服务器发过来的该文件的最后服务器修改时间。

If-Modified-Since是标准的HTTP请求头标签,在发送HTTP请求时,把浏览器端缓存页面的最后修改时间一起发到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行比较。

如果时间一致,那么返回HTTP状态码304(不返回文件内容),客户端接到之后,就直接把本地缓存文件显示到浏览器中。

如果时间不一致,就返回HTTP状态码200和新的文件内容,客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示到浏览器中。

下面用一个简单的小例子说明一下。

由于演示例子需要截取HTTP Request和Response的信息,我在这里使用的工具是Fiddler。
感兴趣的朋友可以到【http://www.fiddler2.com/Fiddler2/version.asp】去下载。

1.首先在服务器创建一个简单的HTML文件,用浏览器访问一下,成功表示HTML页面。Fiddler就会产生下面的捕获信息。
  需要留意的是
  (1)因为是第一次访问该页面,客户端发请求时,请求头中没有If-Modified-Since标签。
  (2)服务器返回的HTTP状态码是200,并发送页面的全部内容。
  (3)服务器返回的HTTP头标签中有Last-Modified,告诉客户端页面的最后修改时间。  
  
2.在浏览器中刷新一下页面,Fiddler就会产生下面的捕获信息。
  需要注意的是
  (1)客户端发HTTP请求时,使用If-Modified-Since标签,把上次服务器告诉它的文件最后修改时间返回到服务器端了。
  (2)因为文件没有改动过,所以服务器返回的HTTP状态码是304,没有发送页面的内容。

3.用文本编辑器稍微改动一下页面文件,保存。再用浏览器访问一下,Fiddler就会产生下面的捕获信息。
需要留意的是
  (1)客户端发HTTP请求时,使用If-Modified-Since标签,把上次服务器告诉它的文件最后修改时间返回到服务器端了。
  (2)因为文件被改动过,两边时间不一致,所以服务器返回的HTTP状态码是200,并发送新页面的全部内容。
  (3)服务器返回的HTTP头标签中有Last-Modified,告诉客户端页面的新的最后修改时间。

HTTP的If-Modified-Since头标签与客户端缓存相互配合,大大节约了网络流量。

HTTP缓存 - If-Modified-Since与Last-Modified

2015-04-14 17:34:38|  分类: HTTP |  标签:http  缓存  if-modified-since  last-modified  |举报|字号 订阅

下载LOFTER我的照片书  |

概述

当浏览器本地缓存的数据已经过期或无法判断是否为最新版本,就会向服务器发起请求进行核对,常见的是Last-ModifiedIf-Modified-Since结合使用。

  • 如果自指定的时间之后,文档发生了变化,就返回文档内容和新的修改时间,浏览器用新的数据覆盖本地缓存。
  • 如果文档没有变化,返回304 Not Modified,只返回一些需要在浏览器中更新的Header信息。

注:一些WEB服务器在实现时,只是比较If-Modified-Since与文档的修改时间是否一致,并没有确认是否在这个时间之后修改过。

实例

首次请求与响应

1)浏览器首次访问时,请求的Header中没有If-Modified-Since。
2)响应状态码为200,响应的Header中返回了Last-Modified并完整地返回了文件内容。

本地有缓存,文档在服务器未修改

1)浏览器再次访问,请求的Header携带了If-Modified-Since,其值为上次响应的Last-Modified的时间。
2)此文件没有修改过,服务器返回响应状态码为304,响应的Body为空。

本地有缓存,文档在服务器有修改

1)在服务器修改文件。
2)浏览器的请求的Header携带If-Modified-Since。
3)由于文件已修改并且比If-Modified-Since的时间新,因此响应状态码为200,返回文件内容并在响应的Header中返回了Last-Modified,其值为文件的最新修改时间。

<正文结束>

Last-Modified、If-Modified-Since 实现缓存和 OutputCache

发布时间:2015-03-24 21:03 点击:638次 文章作者:admin

先梳理三个概念:

  • OutputCache:页面输出缓存,一般 ASP.NET 应用程序会用到。
  • Last-Modified:Http 响应头(Http Reponse Header),由服务器发给客户端,格式为 Last-Modified:Tue, 24 Mar 2015 06:40:46 GMT
  • If-Modified-Since:Http 请求头(Http Request Header),由客户端发给服务器,格式为 If-Modified-Since:Tue, 24 Mar 2015 06:40:46 GMT

还有两个 HTTP 状态码:

  • 200(成功):正常状态,服务器已成功处理了请求,每次都有客户端和服务端的交互。
  • 304(未修改):自从上次请求后,请求的网页未修改过,服务器返回此响应时,不会返回网页内容。如果网页自请求者上次请求后再也没有更改过,将服务器配置为返回此响应(If-Modified-Since HTTP),服务器可以告诉客户端网页没有变更,进而节省带宽和开销。

如果我们的应用程序没有进行任何的缓存处理,客户端在每次浏览页面的时候,Last-Modified 和 If-Modified-Since 的响应值都为 NULL,并且 HTTP 状态码为 200,这没什么问题。我们下面要做的工作先使用 OutputCache 实现缓存,代码很简单:

public static int index = 0; [OutputCache(Duration = 120)] public ActionResult About() { FileHelper.Write(@"C:\Users\xishuai\Desktop\test.txt", (index+1).ToString()); ViewBag.Message = "Message:" + index++; return View(); }

第一次请求:

  • Status Code:200
  • Last-Modified:Tue, 24 Mar 2015 07:13:46 GMT
  • If-Modified-Since:NULL
  • test.txt:0
  • Message:0

第二次请求:

  • Status Code:304
  • Last-Modified:Tue, 24 Mar 2015 07:13:46 GMT
  • If-Modified-Since:Tue, 24 Mar 2015 07:13:46 GMT
  • test.txt:0
  • Message:0

第三次请求:

  • Status Code:304
  • Last-Modified:Tue, 24 Mar 2015 07:13:46 GMT
  • If-Modified-Since:Tue, 24 Mar 2015 07:13:46 GMT
  • test.txt:0
  • Message:0

Message 和 test.txt 里面的值一直为 0,Message 是为了测试页面缓存有没有生效,test.txt 是为了测试 About Action 有没有执行,这两个值的测试结果是我们想要的。另外,可以看到,第一次刷新的时候,Last-Modified 是有值的,而 If-Modified-Since 却没有值,这是因为 Last-Modified 是服务器发给客户端,而 If-Modified-Since 的产生必须要要通过 Last-Modified,并且是由客户端发给服务器,这个在第二次刷新的时候就可以看到,在页面输出缓存的 120 秒内,这两个值会一直不变。

dudu 之前的两篇博文:

出现的问题就是我们在第三次请求的时候,HTTP 状态码为 200,之前的解决方式是 Response.Cache.SetOmitVaryStar(true);,这个我在做测试的时候没有遇到,使用的是 MVC 5.2.2,微软应该是修复了。



上面是 ASP.NET 中使用 OutputCache 进行缓存的处理,我们一般也是这么用的,根据对 Last-Modified 和 If-Modified-Since 的理解,我们能不能使用它们,来实现 OutputCache 的一些效果呢?下面我们来尝试下,简单代码:

public static int index = 0; public ActionResult About() { string dt = Request.Headers["If-Modified-Since"]; DateTime isModifiedSince; if (!string.IsNullOrEmpty(dt)) { if (DateTime.TryParse(dt, out isModifiedSince)) { if (isModifiedSince.AddSeconds(120) < DateTime.Now) { Response.Cache.SetLastModified(DateTime.Now); } } } else { Response.Cache.SetLastModified(DateTime.Now); } FileHelper.Write(@"C:\Users\xishuai\Desktop\test.txt", (index+1).ToString()); ViewBag.Message = "Message:" + index++; return View(); }

先说下上面代码的意思,首先获取请求头中 If-Modified-Since 的值,如果没有值的话,就通过 SetLastModified 设置响应头中 Last-Modified 的值,如果有值的话,进行时间间隔判断,如果在 120 秒之外,则更新 Last-Modified 的值,否则不更新,我们来看下测试结果。

第一次请求:

  • Status Code:200
  • Last-Modified:Tue, 24 Mar 2015 07:34:58 GMT
  • If-Modified-Since:NULL
  • test.txt:0
  • Message:0

第二次请求:

  • Status Code:200
  • Last-Modified:NULL
  • If-Modified-Since:Tue, 24 Mar 2015 07:35:46 GMT
  • test.txt:1
  • Message:1

第三次请求:

  • Status Code:200
  • Last-Modified:Tue, 24 Mar 2015 07:36:03 GMT
  • If-Modified-Since:NULL
  • test.txt:2
  • Message:2

这是什么情况?和 OutputCache 的效果也差太多了吧,总的来说,HTTP 的状态码一直为 200,test.txt 和 Message 的值一直在发生变化,也就是说“缓存”没有一点效果,而 Last-Modified 和 If-Modified-Since 则更奇怪,一会有值,一会没值。其实很正常,如果 HTTP 的状态码为 200,当一个请求发起的时候,首先设置 Last-Modified 的值,而 If-Modified-Since 则是在下个请求才能生效,因为生效了,所以第二次请求的时候,我们并没有设置 Last-Modified 的值,所以第一次和第二次的请求结果就是上面所示,下面的请求就是重复第一次和第二次请求。

我们知道,Last-Modified 和 If-Modified-Since 的结果和 HTTP 的状态码有关,下面我们再来修改下代码:

public static int index = 0; public ActionResult About() { string dt = Request.Headers["If-Modified-Since"]; DateTime isModifiedSince; if (!string.IsNullOrEmpty(dt)) { if (DateTime.TryParse(dt, out isModifiedSince)) { if (isModifiedSince.AddSeconds(120) < DateTime.Now) { Response.Cache.SetLastModified(DateTime.Now); Response.StatusCode = 200; } else { Response.StatusCode = 304; } } else { Response.StatusCode = 304; } } else { Response.Cache.SetLastModified(DateTime.Now); Response.StatusCode = 200; } FileHelper.Write(@"C:\Users\xishuai\Desktop\test.txt", (index+1).ToString()); ViewBag.Message = "Message:" + index++; return View(); }

你可以看到我们想要做的目的吧,就是手动设置 HTTP 状态码,我们来看下测试结果。

第一次请求:

  • Status Code:200
  • Last-Modified:Tue, 24 Mar 2015 07:49:07 GMT
  • If-Modified-Since:NULL
  • test.txt:0
  • Message:0

第二次请求:

  • Status Code:304
  • Last-Modified:NULL
  • If-Modified-Since:Tue, 24 Mar 2015 07:49:07 GMT
  • test.txt:1
  • Message:0

第三次请求:

  • Status Code:304
  • Last-Modified:NULL
  • If-Modified-Since:Tue, 24 Mar 2015 07:49:07 GMT
  • test.txt:2
  • Message:0

说实话,就差一点和 OutputCache 的效果一样,那差的是什么呢?其实就是 test.txt 里的值,在使用 OutputCache 的时候,这里面的值是不变的,也就是说 About Action 没有被执行,而我们上面测试显示,About Action 是执行的,对于 Message 来说,浏览器显示的是缓存后的值,我们可以得出这样的结论:当使用 OutputCache 的时候,客户端只是向服务器发起一个 Request,仅此而已,这个我们在 Application_BeginRequest 事件中监控到,其余的页面显示完全是客户端缓存的结果,当然,前提方式缓存方式是客户端。

还有一个有意思的地方是,在使用 OutputCache 的时候,除了第一次请求外,其他请求结果中,Last-Modified 和 If-Modified-Since 的值是不变的,根据上面测试的结果,我们可以得出,If-Modified-Since 是 Last-Modified 设置之后的结果,If-Modified-Since 可以一直不变,只要 HTTP 状态码为 304,并且我们没有对 Last-Modified 进行设置。而在使用 OutputCache 的时候,除了 If-Modified-Since 的值一直没变,Last-Modified 的也一直没变,这个有点诡异,应该是把请求和响应头中的值也进行了缓存。

参考资料:

爬虫入门到精通-headers的详细讲解(If-modified-since)

爬虫

5 个月前

本文章属于爬虫入门到精通系统教程第九讲

本文讲解的知识点是headers里面的If-modified-since

直接开始案例把

本次我们要抓取的内容是苹果应用商店里面的所有app 从 iTunes 下载的 App Store

当我第一次打开王者荣耀:在 App Store 上的内容网页的时候,再次刷新的时候,你会看到http状态码返回 304

那么知道了这个http状态码304对我们爬虫有什么用呢?

当我需要每天的爬取苹果应用商店的app的时候,因为苹果app很多,所以每次如果我全部爬取的话,会花费很多的时间,其实我只要抓取有更新的内容就好了。那么http状态码304就派上用场了。

看代码把

import requests

headers = {‘User-Agent‘:‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36‘}

url = ‘https://itunes.apple.com/cn/app/%E7%8E%8B%E8%80%85%E8%8D%A3%E8%80%80/id989673964‘

z = requests.get(url,headers=headers)

# 获取上次修改时间
last_modified = z.headers[‘Last-Modified‘]

# 修改headers
headers[‘If-Modified-Since‘] = last_modified
  • 方法1
    • z1 = requests.get(url,headers=headers)
      print z1.status_code
      # 304
      # 可以看到已经返回状态码304,表示网页没有更新
      
  • 方法2
    • z2 = requests.head(url,headers=headers)
      if z1.headers[‘Last-Modified‘] == last_modified:
          print u‘网页没有更新‘
      # 这种方法也可以知道网页是否有更新
      

总结

那么假如我要每天爬取苹果应该商店的app,那么我会在第一次请求的时候吧每个网页的上次修改时间存到数据库(也就是If-Modified-Since)

然后在我第二次爬取的时候,我会把上次存到数据库的时间放到headers里面,如果http状态码返回304,则表示网页没有更新,我可以不用再次解析网页,这样会节约大量时间...

最后代码在 kimg1234/pachong

时间: 2024-08-06 14:06:34

HTTP的请求头标签 If-Modified-Since的相关文章

http请求头响应头及状态码列表

HTTP响应头和请求头信息对照表 HTTP请求头提供了关于请求,响应或者其他的发送实体的信息.HTTP的头信息包括通用头.请求头.响应头和实体头四个部分.每个头域由一个域名,冒号(:)和域值三部分组成. 通用头标:即可用于请求,也可用于响应,是作为一个整体而不是特定资源与事务相关联. 请求头标:允许客户端传递关于自身的信息和希望的响应形式. 响应头标:服务器和于传递自身信息的响应. 实体头标:定义被传送资源的信息.即可用于请求,也可用于响应. 根据以上分类的HTTP请求头介绍可以参考此文,本工具

http请求头信息

1.HTTP Request Header 请求头信息对照表 Header 解释 示例 Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html Accept-Charset 浏览器可以接受的字符编码集. Accept-Charset: iso-8859-5 Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型. Accept-Encoding: compress, gzip Accept-Language 浏览器可接

http请求头

GET / HTTP/1.1 Host:  www.baidu.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 Connection: Keep-Alive POST / HTTP/1.1 Host:  www.baidu.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en

HTTP协议及其请求头分析

众所周知,Internet的基本协议是TCP/IP协议,目前广泛采用的FTP.Archie Gopher等是建立在TCP/IP协议之上的应用层协议,不同的协议对应着不同的应用.  WWW服务器使用的主要协议是HTTP协议,即超文体传输协议.由于HTTP协议支持的服务不限于WWW,还可以是其它服务,因而HTTP协议允许用 户在统一的界面下,采用不同的协议访问不同的服务,如FTP.Archie.SMTP.NNTP等.另外,HTTP协议还可用于名字服务器和分布式对象管 理.  HTTP的早期版本为HT

HTTP 请求头 &amp; 响应头

HTTP请求头概述 HTTP客户程序(例如浏览器),向服务器发送请求的时候必须指明请求类型(一般是GET或者POST).如有必要,客户程序还可以选择发送其他的请求头.大多数请求头并不是必需的, 但Content-Length除外.对于POST请求来说Content-Length必须出现. 下面是一些最常见的请求头 Accept:浏览器可接受的MIME类型. Accept-Charset:浏览器可接受的字符集. Accept-Encoding:浏览器能够进行解码的数据编码方式,比如gzip.Ser

Http请求头和相应头分析

<海棠> 苏轼 东风袅袅泛崇光,香雾空蒙月转廊: 只恐夜深花睡去,故烧高烛照红妆. 1.Http请求头: 1.1Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 意思:浏览器支持的请求 MIME 类型分别是 text/html.application/xhtml+xml.application/xml 和 */*,优先顺序是它们从左到右的排列顺序 详解: Accept表示浏览器支持的 MIME 类型:

HTTP请求头详解

通常HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息.这两种类型的消息由一个起始行,一个或者多个头域,一个只是头域结束的空行和 可选的消息体组成.HTTP的头域包括通用头,请求头,响应头和实体头四个部分.每个头域由一个域名,冒号(:)和域值三部分组成.域名是大小写无关的, 域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符. 通用头域 通用头域包含请求和响应消息都支持的头域,通用头域包含Cache-Control. Connection

[面试没答上的问题1]http请求,请求头和响应头都有什么信息?

最近在找工作,面试官问了一些问题自己并没有回答上,这里做一个小结. http请求,请求头和响应头都有什么信息? 页面和服务器交互最常见的方式就是ajax,ajax简单来说是浏览器发送请求到服务端,然后服务端返回数据,常见的请求头和响应头如下图所示. 先看通用信息,通用信息有三个字段: 请求url, 请求方法, 状态码, 远程地址. 看下请求头Request Headers, Accept : 指定客户端能够接收的内容类型,内容类型中的先后次序表示客户端接收的先后次序.在Ajax代码中,可以使用X

HTTP响应头和请求头信息对照表

HTTP请求头提供了关于请求,响应或者其他的发送实体的信息.HTTP的头信息包括通用头.请求头.响应头和实体头四个部分.每个头域由一个域名,冒号(:)和域值三部分组成. 通用头标:即可用于请求,也可用于响应,是作为一个整体而不是特定资源与事务相关联. 请求头标:允许客户端传递关于自身的信息和希望的响应形式. 响应头标:服务器和于传递自身信息的响应. 实体头标:定义被传送资源的信息.即可用于请求,也可用于响应. 根据以上分类的HTTP请求头介绍可以参考此文,本工具根据请求和输出分为Request和