Để quyết định 1 file có cần phải call to original server ko, ta dựa vào trạng thái STALE hay FRESH của file. Để biết file ở trạng thái nào, file dựa trên Last-modified hoặc Etag header.

1) Last modified
If-Modified-Since: Wed, 22 Feb 2006 04:15:54 GM
# Response header:
HTTP/1.1 304 Not Modified
Last-Modified: Wed, 22 Feb 2006 04:15:54 GMT
Ở một số server, hệ thống không parse được kiểu DateTime này nên Etag được sinh ra đời.
2) Etag
If-None-Match: W/"3f49v0adw9c9v89fbdb8oqwe998ac0vd97glq3c9
# Response header:
HTTP/1.1 304 Not Modified
Etag: W/"3f49v0adw9c9v89fbdb8oqwe998ac0vd97glq3c9
3) Expires
Trước đây khi chưa có HTTP1.1, thì header dựa trên Expires để biết request đó còn valid ko, có cần gọi tới origin server để kiểm tra ko.
Nhưng ngày nay, khi Cache-Control ra đời, thì người ta chủ yếu dựa trên thuộc tính này để biết request đó còn valid ko, nếu có cả Expires và Cache-Control thì Cache-Control max-age được ưu tiên hơn
Expires: Fri, 08 Dec 2023 20:50:21 GMT
4) Cache-Control
Cache-Control: public, max-age=3600, must-revalidate
Cache-Control độ ưu tiên cao hơn Expires, bao gồm nhiều directives để thiết lập việc caching browser cũng như shared-cache (CDN, Proxies…)
Một số directives phổ biến như:
public: cho phép cache ở mọi nơi có thể, client browser, shared cache (CDN, cloudflare..), phục vụ nhiều users.
private: cache only cho một client browser nhất định, ko được cache trên server cache (CDN, cloudflare…)
max-age: thời gian tối đa mà request ở trạng thái FRESH, lấy trực tiếp từ cache và không cần validate lại ở original-server
must-revalidate: chỉ thị phải validate với origin server khi request ở trạng thái STALE, nếu request ở trạng thái FRESH thì vẫn lấy data trực tiếp từ cache.
Ví dụ: với request max-age=60, must-revalidate có nghĩa là nếu request được gọi trong khoảng thời gian <60 thì request lấy trực tiếp từ cache mà ko cần validate, sau khoảng thời gian từ 60, thì buộc phải validate origin server.
- Nếu server thấy Last-Modified hoặc Etag ko có gì thay đổi, khớp với If-Modified-Since hoặc If-None-Match được gửi trong request header thì trả về status 304 và lấy data từ Cache.
- Nếu server thấy không khớp thì sẽ thực hiện lại logic để lấy data như lần đầu request gọi đến và trả về status 200 cho client cũng như cache trong server cache, thời gian max-age cũng được refresh lại từ đầu.
no-cache: tương đương với max-age=0, must-revalidate, có nghĩa là request luôn luôn ở trạng thái STALE và bắt buộc luôn luôn phải kiểm tra lại trạng thái latest ở phía origin server.
no-store: không được phép cache, request luôn luôn phải gọi đến origin server và tính toán logic để lấy data trả về.
Keep-alive: thể hiện các request đến cùng 1 server, thay vì phải mở nhiều socket đến cùng 1 server.
Browser-server sẽ close connection khi tham số truyền vào là Connection: close
Mặc định ko cần thêm trong HTTP/1.1, nhưng hầu hết browser và server vẫn include nó.
# Custom keep-alive
# The connection is closed after 5 seconds of inactivity and can be reused 100 times.
Keep-Alive timeout=5, max=100
# Request header
GET /us.js.yimg.com/lib/common/utils/2/yahoo_2.0.0-b2.js HTTP/1.1
Host: us.js2.yimg.com
User-Agent: Mozilla/5.0 (...) Gecko/20061206 Firefox/1.5.0.9 Accept-Encoding: gzip,deflate
Connection: keep-alive
# Response header
HTTP/1.1 200 OK
Content-Type: application/x-javascript
Last-Modified: Wed, 22 Feb 2006 04:15:54 GMT
Connection: keep-alive
# Check rails log
it will not render view template, just return 304 Not Modified
Việc cache 1 request, server cache based trên url, nên để khắc phục nhược điểm server ko cache khi thay đổi content nội dung của file, ta đánh version cho file. vd file-name-12345.js hoặc filename.js?v=12345. Hiện tại với rails thì khi deploy lên production, những file css hay js thì đều đã được hash file name khi content file được thay đổi rồi.
Example Caching 1:

1) Lần đầu gọi, có request header, có tính toán logic và trả về status 200, content lưu vào cache

2) Những lần sau trong khoảng thời gian nhỏ hơn 60s (max-age=60), request lấy trực tiếp từ cache (200 OK from memmory cache) và ko có request header

3) Sau khoảng thời gian 60s, file ở trạng thái STALE và request phải gọi tới origin server để kiểm tra xem file có thay đổi gì ko (dựa vào If-Modified-Since hoặc If-None-Match). Nếu không thì trả về status 304 Not Modified và lấy content từ cache (như hình dưới). Nếu file có thay đổi thì tính toán logic để lấy content và trả về status 200 như ở bước 1

4) Ở những request tiếp theo trả về 200 OK from memory cache như ở bước 2

Example caching 2:

Cache-Control tương đương với public, no-cache. Do max-age=0, có nghĩa là file luôn ở trạng thái STALE, nên lúc nào call request cũng phải validate với origin-server
1) Ở lần đầu gọi request tới, trả về status 200 và có request header, content được lưu vào cache

2) Ở những lần tiếp theo, phải validate phía server, nếu ko có gì thay đổi thì luôn luôn trả về status 304 Not Modified và lấy content từ cache (như hình dưới). Nếu có thay đổi thì tính toán để lấy lại data và trả về status 200 như ở bước 1

- no-cache(max-age=0, must-revalidate): file stale, và alway call to server to validate
→ return 200 if file updated with body
→ return 304 if still valid without body
→ return 304 if still valid without body
→ return 304 if still valid without body