REST笔记(五):你应该知道的HTTP头------ETag

在HTTP1.1规范中,新增了一个HTTP头信息:ETag。对Web开发者来说,它是一个非常重要的信息。它是用作缓存使

用的两个主要的头信息之一 (另一个是Expires)。除此之外,在REST架构中,它还可以用于控制并发操作(上节中已经大

致介绍AtomPub中控制并发的流程)。那么ETag是什么?它又几种类型?强ETag与弱ETag之间有什么区别。?如何计算

ETag值?它与Last-Modified头信息在使用上有什么区别?本节主要围绕这几个方面叙述一下自己的理解。


目录:

  1. 什么是ETag?
  2. 计算ETag值
  3. ETag的类型以及他们之间的区别
  4. ETag与Last-Modified头信息用途上的区别

什么是ETag? 

ETag:是实体标签(Entity Tag)的缩写。ETag一般不以明文形式相应给客户端。在资源的各个生命周期中,它都具有不

值,用于标识出资源的状态。当资源发生变更时,如果其头信息中一个或者多个发生变化,或者消息实体发生变化

,那ETag也随之发生化。

ETag值的变更说明资源状态已经被修改。往往可以通过时间戳就可以便宜的得到ETag头信息。在服务端中如果发回给

消费者的相应一开始起就由ETag控制,那么可以确保更细粒度的ETag升级完全由服务来进行控制。服务计算ETag值,

并在相应客户端请求时将它返回给客户端。

计算ETag值

在HTTP1.1协议中并没有规范如何计算ETag。ETag值可以是唯一标识资源的任何东西,如持久化存储中的某个资源关联

的版本、一个或者多个文件属性,实体头信息和校验值、(CheckSum),也可以计算实体信息的散列值。有时候,为了计

算一个ETag值可能有比较大的代价,此时可以采用生成唯一值等方式(如常见的GUID)。无论怎样,服务都应该尽可能的

将ETag值返回给客户端。客户端不用关心ETag值如何产生,只要服务在资源状态发生变更的情况下将ETag值发送给它就行

。下图为MSDN中,OutgoingResponse类中设置ETag值的截图:

2011-12-24_105957

从上图可以看出,在REST架构下,ETag值可以通过Guid、整数、长整形、字符串四种类型的参数传入SetETag方法,

WCF服务发回给客户端的HTTP响应头中就包含了ETag值。另外OutgoingResponse类也有字符串属性:ETag直接给

它赋值也能在HTTP响应头中写入ETag值。

如下所示为使用文件属性计算ETag:

 public class ETag : IHeader
    {
        private string Value;

        public ETag(string value)
        {
            Value = value;
            WebOperationContext.Current.OutgoingResponse.ETag
        }

        #region IHeader 成员

        public void AddHTTPHeader(ResponseContext context)
        {
            context.WriteHttpHeader(Value);
        }

        #endregion
    }
获取ETag:
ETag eTag = new ETag(fileInfo.Name+fileInfo.LastWriteTimeUtc.ToString())

计算ETag值时,需要考虑两个问题:计算与存储。如果一个ETag值只需要很小的代价以及占用很低的存储空间,那么

我们以在每次需要发送给客户端ETag值值的时候计算一遍就行行了。相反的,我们需要将之前就已经计算并存储好

的ETag值发送给客户端。之前说:将时间戳作为字符串作为一种廉价的方式来获取ETag值。对于不是经常变化的消息,

它是一种足够好的方案。注意:如果将时间戳做为ETag值,通常不应该用Last-Modified的值。由于HTTP机制中,所

以当我们在通过服务校验资源状态时,客户端不需要进行相应的改动。计算ETag值开销最大的一般是计算采用哈希算法

获取资源的表述值。可以只计算资源的哈希值,也可以将头信息和头信息的值也包含进去。如果包含头信息,那么注意

不要包含计算机标识的头信息。同样也应该避免包含Expires、Cache-Control和Vary头信息。注意:在通过哈希算法

计算ETag值时,先要组装资源的表述。若组装也比较耗时,可以采用生成GUID的方式。优化ETag值的获取。

ETag的类型以及他们之间的区别

ETag有两种类型:强ETag(strong ETag)与弱ETag(weak ETag)。

强ETag表示形式:"22FAA065-2664-4197-9C5E-C92EA03D0A16"。

弱ETag表现形式:w/"22FAA065-2664-4197-9C5E-C92EA03D0A16"。

强、弱ETag类型的出现与Apache务器计算ETag的方式有关。Apache默认通过FileEtag中FileEtag INode Mtime Siz

e的配置自动生成ETag(当然也可以通过用户自定义的方式)。假设服务端的资源频繁被修改(如1秒内修改了N次),此时

如果有用户将Apache的配置改为MTime,由于MTime只能精确到秒,那么就可以避免强ETag在1秒内的ETag总是不同而

频繁刷新Cache(如果资源在秒级经常被修改,也可以通过Last-Modified来解决)。


ETag与Last-Modified头信息用途上的区别

按照HTTP标准,Last-Modified只能精确到秒级。ETag的出现可以很好的解决这个问题。在用途上,ETag常与

If-None-Match或者If-Match一起,由客户端通过HTTP头信息(包括ETag值)发送给服务端处理。ETag使用如下:

Get /Order/36 Http1.1

If-Match:"22FAA065-2664-4197-9C5E-C92EA03D0A16"

或If-None-Match:"22FAA065-2664-4197-9C5E-C92EA03D0A16"

Last-Modified常与If-Modified-Since一起由客户端将Last-Modified值包括在HTTP头信息中发给服务端进行处理。

其使用如下:

If-Modified-Since:Sat,24 Dec 2011 11:55:36 GMT

posted @ 2011-12-24 12:10  tyb1222  阅读(27158)  评论(2编辑  收藏  举报