Etag緩存在PHP和NodeJS中的實現


HTTP 提供了許多頁面緩存的方案,其中屬 Etag 和 Last-Modified 應用最廣。本文會先介紹 Etag 的應用場景,然后說說他在 php 和 node 中的使用。

本文地址:http://www.cnblogs.com/hustskyking/p/etag-in-node.html,轉載請注明源地址。

一、Etag的使用

客戶端和瀏覽器之間的交互:

+---------+       1         +---------+
|         |---------------->|         |
|         |   2200,OK)   |         |
|         |<----------------|         |
|    客   |    3(Etag)     |    服   |
|         |---------------->|         |
|    戶   |    4304)      |    務   |
|         |<----------------|         |
|    端   |    3(強制刷新)  |    端   |
|         |---------------->|         |
|         |   6200,OK)   |         |
|         |<----------------|         |
+---------+                 +---------+
                <Created By Barret Lee>

1. 客戶端向服務器請求資源S

2. 服務器返回數據,並帶上一個 Etag

3. 客戶端再次請求資源S,由於上次服務器給他返回了一個 Etag,這次請求的時候他會帶上這個 Etag

4. 服務器發現請求中包含 Etag,判斷是否過期,沒過期則返回 304 Not Modified

5. 客戶端強制刷新(如chrome中ctrl+shift+R刷新頁面),請求中剔除 Etag

6. 服務器未發現請求中包含 Etag,返回資源S,並帶上一個 Etag

二、代碼實現

第一次請求數據:

瀏覽器在接受到服務器發過來的 Etag 后,會保存下來,下次請求的時候會將它放在請求頭中,其 key 值為 If-None-Match。

服務器拿到 If-None-Match 之后,對比之前的 Etag,如果沒變,則返回 304 Not Modified.

1. php 中的 Etag

<?php
    $str = "Barret Lee";
    $Etag = md5($str);

    if(array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER) and $_SERVER['HTTP_IF_NONE_MATCH'] == $Etag){
        header("HTTP/1.1 304 Not Modified");
        exit();
    } else {
        header("Etag:" . $Etag);
        echo $str;
    }
?>

Etag 是一個字符串,我們一般使用該請求對應響應輸出的 md5 值作為 Etag,可以簡單地理解為文件的版本號。在 php 中存在兩個獲取 md5 的函數,一個是針對字符串的,就是 md5(),然后就是針對文件的, md5_file()

首先判斷在請求中是否包含 'HTTP_IF_NONE_MATCH' 這個 key,如果包含並且其值為之前的 md5 值,則返回 304,否則輸出 Etag 以及內容。

2. node 中的 Etag

與 php 有些不同,從 $_SERVER 中拿到的內容是經過 apache 包裝過的,而 node 獲取的數據是最原始的。

var hashStr = "A hash string.";
var hash = require("crypto").createHash('sha1').update(hashStr).digest('base64');

require("http").createServer(function(req, res){
    if(req.headers['if-none-match'] == hash){
        res.writeHead(304);
        res.end();
        return;
    }
    res.writeHead(200, {
        "Etag": hash
    })
    res.write(hashStr);
    res.end();
}).listen(9999);

上面對 hashStr(輸出的內容) 進行了簡單的處理,並將其作為 Etag 放在 head 中輸出,上面的代碼一目了然,我就不解釋了。

三、小結

Etag 在緩存處理中用的比較廣泛,使用它可以減少一些不必要請求的帶寬的占用。服務器輸出的內容不變,瀏覽器就應該使用緩存,沒必要每次都向服務器端索要數據,造成不必要的浪費。

從上面我們可以看到,如果想拿到 Etag,就必須先拿到要輸出的數據,所以 Etag 只能減少帶寬的占用,並不能降低服務器的消耗。如果是靜態頁面,可以判斷文件最近一次的修改時間(Last-Modified),獲取文件上次修改時間的消耗比拿到整個數據的消耗要小的多。所以很多時候 Etag 都是配合這 Last-Modified 一起使用的。

上面的 php 和 node 代碼演示,很明顯的差異就是,node 更加細致,或者說他更加底層,我們可以獲取的幾乎都是未加修飾的原始數據,從數據量的交互和可操控性來看,我更偏向於 node 的使用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM