HTTP 協議 / 請求&Cache / 回應&Content-Type


Posted by hoyi-23 on 2021-10-03

主要特點

  1. 支援 客戶端 與 伺服器端
  2. 簡單快速: 只需要傳送請求方法(GET、POST、HEAD)與路徑
  3. HTTP允許傳輸任一類型的數據對象,由Content-Type標記就可以
  4. 無連接: 限制每次連接只處理一個請求(從客戶請求到收到答應就斷開)。這個特點可以節省傳輸時間。
  5. 無狀態:對事務處理沒有記憶能力。

HTTP協議與URL

HTTP就是一個客戶端發請求,伺服器端回應的一個協議。基於TPC的連接方式。
http://host[":"port][abs_path]
host: 合法的網路主機域名或IP位址
port: 一個端口號(為空的話則為80)
abs_path: 如果沒有給abs_path,當作為請求URL時,會以/這個形式給出。

HTTP協議 請求

請求包含三區塊:

  1. Request Headers/Method/Request Url(包含 請求方式 與 請求的URL和協議版本)
  2. 指定要請求資料的網路主機或端口號
  3. Message Body請求的內容

例如:

GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr

請求方法 request method

  • GET : GET方法就是要請求資料,而請求資料時只用GET。
  • POST : POST方法是提交內容,通常會造成伺服器端上的一些改變。
  • HEAD : HEAD方法是要請求一個回應(與GET相同),不同於GET的是,不需要回應的內容(只需要回應首行)。
  • PUT : PUT方法請求伺服器儲存一個資料
  • DELETE : 請求刪除一個資料
  • TRACE : 追蹤資料,請求伺服器端回送收到的請求訊息。(主要用在診斷或測試)
  • CONNECT : 請求針對特定的資料建立一個管道
  • OPTIONS : 請求查詢伺服器的性能或查詢特定資料
  • PATCH : 修改資料

cache 快取

為什麼需要cache 快取?
cache的用處是為了節省流量、節省時間然後節省資源耗損。
如果今天每一個訪客到首頁都要讓你重新到資料庫抓資料,這樣對資料庫的負擔會很大,假如說這個網站並不是短期之內會有變動的,那就可以使用cache快取(也可以說緩存)。
簡單來說,就是第一次撈資料後,就先把資料存到某個地方,之後如果需要,就可以用極快的方式取到,也不用要重新請求資料庫。

伺服器與瀏覽器間的Cache機制

要達成瀏覽器先把照片Cache起來,可以在HTTP Response Header 裡面加上一個Expires,裡面就是這個 Cache 到期的時間,例如:

Expires: Sat, 31 Dec 2022 00:00:00 GMT

如果沒有超過這個時間,瀏覽器就不會從後端取資料,而是直接從電腦存好的cache拿。
這個時間是以電腦的時間為基準,所以如果刻意更改時間,讓他超過expires date,瀏覽器就會在發送新的request。

cache-control

為了應對上面的問題,就有了cache control(cache control也不只解決這個問題)。
其中的一個用法就是 max-agemax-ageexpired一樣,都是可以用來設定cache過期時間,但是expired設定到期日期,而max-age設定從第一次抓資料後,經過多少秒數會過期。
如果同時設定了expiredmax-age,會看max-age喔!

如果是機密資料,不想要任何快取呢?
可以使用cache-control: no-store

過期之後 ...

cache到期後,有兩條路

  1. (資料有改變)重新請求資料,伺服器重新給資料
  2. (資料都沒改變)重新請求資料,伺服器說:資料都一樣,所以可以繼續用原本的快取喔!

要做到這樣的判斷,需要在客戶端第一次抓資料時,伺服器傳回response的Header上加上Last-Modified,來標示這個檔案最後的更改時間。
等到下一次客戶端要在取資料時,可以再request的header上加上If-Modified-Since,來告訴伺服器,上次的資料最後修改日期,伺服器就會判斷在這之後有沒有修改,若有就會給客戶新資料,若無,就會回傳Status code: 304 (Not Modified)

上面這個方法是用修改日期來看,但是修改的定義,只要將檔案打開再儲存關起來,就算沒改內容也算是修改。
所以有另一個方法是看檔案內容有沒有一樣。
EtagIf-None-Match

伺服器第一次傳資料回應時,會帶上Etag(檔案獨有的),等cache過期,瀏覽器會再發送帶有If-None-Match的請求,伺服器判斷有沒有相同。

如果不會常常變動資料,但是又希望資料再變動後馬上讓客戶端取到呢?
  1. 搭配max-ageEtag
    先設定Cache-Control: max-age=0,讓客戶一拿到資料,0秒後cache就過期,等客戶再造訪網頁(重整..)後,就會再重抓資料,但是因為同時也有附上Etag。所以客戶端的請求會帶上If-None-Match,伺服器就可以判斷是否需要重新傳送。
  2. Cache-control: no-cache
    Cache-control: no-store不同,
    Cache-control: no-store是永遠不要快存。
    Cache-control: no-cache是永遠檢查快存。

最後還會遇到一個問題,因為現在通常會做SPA架構,透過Webpack打包,只需要引入script就好。
通常index.html的body內部是空的,這樣要怎麼讓客戶端發現內容有更動呢?

將Etag寫入檔案內

解決方法就是,將Etag寫入引入的script名稱(例如:script-123abc.js 下一次更改時改為script-456def.js)


Content-Type

HTTP請求的Content-Type會出現在POST或PUT時,讓客戶端告訴伺服器自己傳的資料是什麼內容類型。


HTTP協議 回應

HTTP/1.1 200 OK
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html

HTTP 回應狀態碼

  • 1XX 訊息類 (收到請求,請求者繼續執行操作)
  • 2XX 成功類 (操作被成功接受並處理),例如:200 成功回應
  • 3XX 重定向類 (需進一步操作才能完成),例如:301 成功轉向
  • 4XX 客戶端錯誤類 (請求語法錯誤或無法完成請求) 例如:404 找不到資源
  • 5XX 伺服器錯誤類 (後端的問題),例如:500 伺服器錯誤

Content-Type

在回應中Content-Type 用來表示資源的 media type。
瀏覽器有時會自己推測內容類型(MIME sniffing),如果要阻止這個行為,可以在回應中設定 X-Content-Type-Options 標頭為 nosniff。


#HTTP協議 #cache







Related Posts

在 Ethereum 上開發簡單的 Todo App

在 Ethereum 上開發簡單的 Todo App

[PHP] 物件導向 PHP 入門

[PHP] 物件導向 PHP 入門

Day06: GraphQL - Enumeration and list types wiht node.js

Day06: GraphQL - Enumeration and list types wiht node.js


Comments