1. 程式人生 > >【web】HTTP頭 中ETag

【web】HTTP頭 中ETag

REST筆記(五):你應該知道的HTTP頭——ETag

在HTTP1.1規範中,新增了一個HTTP頭資訊:ETag。對Web開發者來說,它是一個非常重要的資訊。它是用作快取使

用的兩個主要的頭資訊之一 (另一個是Expires)。除此之外,在REST架構中,它還可以用於控制併發操作(上節中已經大

致介紹AtomPub中控制併發的流程)。那麼ETag是什麼?它又幾種型別?強ETag與弱ETag之間有什麼區別。?如何計算

ETag值?它與Last-Modified頭資訊在使用上有什麼區別?本節主要圍繞這幾個方面敘述一下自己的理解。

目錄:

什麼是ETag?
計算ETag值
ETag的型別以及他們之間的區別
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())
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

}
1

獲取ETag:
1

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