HTTP(超文本傳輸協議)協議通常使用狀態碼來表示服務器的響應狀態。其中,狀態碼為304表示 Not Modified,該狀態碼通常會在瀏覽器發出請求時被使用。這意味着瀏覽器已經具有請求的資源的最新版本,因此服務器可以選擇不返回內容,而瀏覽器可以從本地緩存中讀取數據,減少了服務器壓力並提高了頁面加載速度。
一、HTTP緩存機制中的Not Modified
在HTTP緩存機制中,當瀏覽器要求訪問某個資源時,它首先檢查緩存中是否存在該資源的拷貝,並檢查該資源在緩存中是否仍然有效。如果緩存中的資源是最新的,則瀏覽器可以直接從緩存中讀取該資源,而不會向服務器發送請求。
當瀏覽器發送條件請求時,服務器將返回狀態碼304,表示該資源未修改,瀏覽器可以直接從緩存中讀取該資源。
下面是一個使用Python的Flask框架來演示的代碼示例:
from flask import Flask, request, make_response app = Flask(__name__) @app.route('/image') def image(): image_file = open("image.png", "rb").read() response = make_response(image_file) response.headers.set('Cache-Control', 'public, max-age=3600') response.headers.set('Content-Type', 'image/png') return response if __name__ == "__main__": app.run()
該代碼使用了Flask框架來啟動一個簡單的HTTP服務器,並向客戶端返回一個示例圖片。由於請求中包含了Cache-Control頭部信息,瀏覽器將在1個小時內緩存該資源。在下一次請求中,客戶端將使用條件請求,並根據服務器的響應決定是否使用緩存來加速頁面加載。
二、使用Etag實現Not Modified
Etag是HTTP協議提供的一種機制,用於檢測資源的內容是否已經被修改。服務器在返回資源時,可以通過設置Etag頭來指定該資源的特徵值。瀏覽器在向服務器發出條件請求時,將Etag頭包含在請求中,服務器可以使用該值來判斷是否有必要返回資源的內容或返回狀態碼304。
下面是一個使用Node.js的Express框架來使用Etag實現Not Modified的代碼示例:
const express = require('express'); const fs = require('fs'); const app = express(); const PORT = 3000; const FILE_PATH = './resources/myfile.txt'; app.get('/file', (req, res) => { fs.readFile(FILE_PATH, (err, data) => { const etag = '"' + generateETag(data) + '"'; if (req.headers['if-none-match'] === etag) { res.status(304).end(); return; } res.set({ 'ETag': etag, 'Content-Type': 'text/plain', 'Cache-Control': 'public, max-age=3600', }); res.send(data); }); }); function generateETag(data) { const hash = require('crypto').createHash('md5'); hash.update(data); return hash.digest('hex'); } app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`); });
該代碼使用了Node.js的Express框架來啟動HTTP服務器,並根據請求返回一個文本文件的內容。通過使用Crypto模塊來計算文件內容的哈希值,並為每個文件資源生成獨立的Etag。在接收到條件請求時,服務器使用實體標籤來檢查資源是否已經過期,從而控制是否返迴響應內容。
三、使用Last-Modified實現Not Modified
Last-Modified是HTTP協議另一種可用於檢測資源是否已經被修改的機制。服務器在返回資源時,可以通過設置Last-Modified頭來指定最新的修改日期和時間。瀏覽器在向服務器發出條件請求時,將If-Modified-Since頭部信息包含在請求中,服務器可以使用該值來決定是否必須返迴響應內容或僅返回狀態碼304。
下面是一個使用Java的Spring框架來使用Last-Modified實現Not Modified的代碼示例:
@RestController public class ApiController { @GetMapping(value = "/api") public ResponseEntity getResource( @RequestHeader(value = "If-Modified-Since", required = false) String modifiedSince) { HttpHeaders headers = new HttpHeaders(); headers.setCacheControl(CacheControl.maxAge(3600, TimeUnit.SECONDS).getHeaderValue()); Path file = Paths.get("/resources/myfile.txt"); FileTime lastModified = Files.getLastModifiedTime(file); headers.setLastModified(lastModified.toMillis()); if (modifiedSince != null) { ZonedDateTime modifiedSinceTime = ZonedDateTime.parse(modifiedSince).withZoneSameInstant(ZoneId.systemDefault()); if (Files.getLastModifiedTime(file).toInstant().toEpochMilli() <= modifiedSinceTime.toInstant().toEpochMilli()) { return ResponseEntity.status(HttpStatus.NOT_MODIFIED).headers(headers).build(); } } String contents = new String(Files.readAllBytes(file), StandardCharsets.UTF_8); return ResponseEntity.ok().headers(headers).body(contents); } }
該代碼使用Spring框架來啟動一個簡單的HTTP服務器,並使用Last-Modified標頭為資源添加最新修改時間戳。當客戶端在隨後的請求中發出條件請求時,服務器使用If-Modified-Since標頭來確定資源是否已過期,從而僅在必要時返回實際數據,減輕了服務器負載。
總結
Not Modified狀態碼是HTTP協議中用於表示資源是否已更新的狀態碼。在HTTP緩存機制中,Not Modified狀態碼可以有效減輕服務器的負擔,提高頁面加載速度;在使用Etag或Last-Modified時,服務器可以檢測資源的內容是否已經被修改,從而在必要時僅返回狀態碼而不是實際數據,減少無謂的網絡傳輸。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/244528.html