http客戶端與瀏覽器的區別


 兩者區別:瀏覽器對http響應頭會進行特定處理(如自動讀取本地緩存、設置cookie等),而http客戶端(如crul)可能沒有像瀏覽器那樣的處理,某些封裝程度高的http客戶端,可能會有。

同一個文件夾中有三個文件:

使用了http標准庫的js客戶端:

const http = require('http');

const options = {
    hostname: '127.0.0.1',
    port: 8080,
    path: '/api',
    method: 'GET'
};

const req = http.request(options, function (res) {
    console.log('STATUS:' + res.statusCode);
    console.log('HEADERS:' + JSON.stringify(res.headers));
    
    res.setEncoding('utf-8');
    let data = "";
    res.on('data', function (chunk) {
        console.log(`接收到數據:${chunk}\r\n`);
        data += chunk;
    });
    res.on('end', function () {
        console.log('響應結束');
        console.log('接收到的數據為:' + data);
    });
});
req.end();

用於瀏覽器發起請求的h5頁面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="msg"></div>
<script>
    var xhr = new XMLHttpRequest();
    xhr.open("GET","http://127.0.0.1:8080/api",true);
    xhr.send(null);

    xhr.onload = function(){
        document.querySelector("#msg").innerHTML = xhr.responseText;
    }
</script>
</body>
</html>

js服務端:

const http = require("http");
const fs = require("fs");
const server = http.createServer(function(req,res){

    res.setHeader('Content-Type','text/html;charset=utf-8');

    switch(true){
        case req.url.startsWith('/index'):
            fs.readFile('./index.html',"utf-8",function (_,data) {
                res.end(data);
            });
            break;
        case req.url.startsWith('/api'):
            console.log(JSON.stringify(req.headers));
            res.end("每次請求都返回一個隨機數:" + Math.random());
            break;
    }
});
server.listen(8080,'127.0.0.1',function(){
    console.log(`服務器運行在8080`);
});

 

后續測試環境為:

訪問地址:http://127.0.0.1:8080/index

以上地址每次訪問,都會顯示不同的隨機數。

測試強緩存

服務器返回數據前,加上個強緩存設置(10s):

case req.url.startsWith('/api'):
    console.log(JSON.stringify(req.headers));
    let curTime = +new Date();
    let cacheOutDateTime = curTime + 10*1000;
    let GMTTime = new Date(cacheOutDateTime).toGMTString();

    res.setHeader('Expires', GMTTime);

    res.end("每次請求都返回一個隨機數:" + Math.random());
    break;

 

瀏覽器訪問地址:http://localhost:8080/index

10s內不停刷新瀏覽器,顯示的隨機數都是一樣的,說明強緩存生效了。

 

通過js客戶端來訪問,強緩存無效:

C:\Users\MRLWJ\Desktop\知識分享10-25\web\srv>node client.js
STATUS:200
HEADERS:{"content-type":"text/html;charset=utf-8","expires":"Wed, 24 Oct 2018 15:58:26 GMT","date":"Wed, 24 Oct 2018 15:58:16 GMT","connection":"close","content-length":"59"}
接收到數據:每次請求都返回一個隨機數:0.005061696884948619

響應結束
接收到的數據為:每次請求都返回一個隨機數:0.005061696884948619

C:\Users\MRLWJ\Desktop\知識分享10-25\web\srv>node client.js
STATUS:200
HEADERS:{"content-type":"text/html;charset=utf-8","expires":"Wed, 24 Oct 2018 15:58:27 GMT","date":"Wed, 24 Oct 2018 15:58:17 GMT","connection":"close","content-length":"57"}
接收到數據:每次請求都返回一個隨機數:0.9111832960061363

響應結束
接收到的數據為:每次請求都返回一個隨機數:0.9111832960061363

通過postman客戶端來訪問也是一樣,強緩存無效。

結論:強緩存的頭(這里測試的是expires)只能作用在瀏覽器上,對於這里的http客戶端無效,因為這里的http客戶端根本就沒有用到那個http頭,更別說還會自己去設置本地緩存了,這些工作瀏覽器才會去做。

測試協商緩存

添加一個etag頭:

case req.url.startsWith('/api'):
    console.log(JSON.stringify(req.headers));

    res.setHeader('Etag', '123');

    res.end("每次請求都返回一個隨機數:" + Math.random());
    break;

 

多次訪問頁面,瀏覽器自動帶上了if-none-match頭

但是協商緩存沒有生效,以上兩個數值明明一樣的。原因在於if-none-match對應的數值,僅僅是給服務端用於校驗而已,如果服務端沒有讀取這個值進行校驗的話,則什么效果都沒有。要有效果的話,則要求服務端校驗完成后,返回個302狀態碼,才能使瀏覽器使用本地緩存。

if-none-match:代表本地已經有緩存了,而且這個緩存的標識符是123。服務器知道這些信息之后,再用於判斷是否需要告訴瀏覽器去使用緩存(是否要返回304)。

假如直接返回304的話,則訪問/api時,雖然能完成請求(打開chrome調試工具,顯示響應狀態碼為304),但響應數據為空:

case '/api':
    console.log(JSON.stringify(req.headers));
    res.statusCode = 304;
    res.end("每次請求都返回一個隨機數:" + Math.random());
    break;

正確的判斷方式,以下設置了304之后,不管有沒有返回正文內容,正文內容都會被忽略

case req.url.startsWith('/api'):
    console.log(JSON.stringify(req.headers));
    res.setHeader('Etag', "123");
    if("123" == req.headers['if-none-match']){
        res.statusCode = 304;
        res.end();
    }
    res.end("每次請求都返回一個隨機數:" + Math.random());
    break;
    }
});

 

修改完成后,用瀏覽器多次請求,都使用的是本地緩存,即顯示到界面上的隨機數一直無變化。

 然后再用js客戶端進行請求,結果如下:

C:\Users\MRLWJ\Desktop\知識分享10-25\web\srv>node client.js
STATUS:200
HEADERS:{"content-type":"text/html;charset=utf-8","etag":"123","date":"Wed, 24 Oct 2018 16:25:53 GMT","connection":"close","content-length":"57"}
接收到數據:每次請求都返回一個隨機數:0.7875283103348185

響應結束
接收到的數據為:每次請求都返回一個隨機數:0.7875283103348185

C:\Users\MRLWJ\Desktop\知識分享10-25\web\srv>node client.js
STATUS:200
HEADERS:{"content-type":"text/html;charset=utf-8","etag":"123","date":"Wed, 24 Oct 2018 16:25:54 GMT","connection":"close","content-length":"57"}
接收到數據:每次請求都返回一個隨機數:0.2601388266595912

響應結束
接收到的數據為:每次請求都返回一個隨機數:0.2601388266595912

結論: 因為這個http客戶端沒有像瀏覽器那樣遵守了http規范,接收到etag時,下次請求時沒有帶上if-none-match,導致服務器沒辦法用於判斷,所以一直返回200,導致協商緩存失效。


免責聲明!

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



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