SyntaxStudy
Sign Up
REST API HTTP Caching with ETags and Cache-Control
REST API Beginner 1 min read

HTTP Caching with ETags and Cache-Control

HTTP caching reduces server load and latency. The Cache-Control header controls who can cache a response and for how long: max-age sets the TTL in seconds; private means only the browser cache (not CDN/proxies) may store it; no-store disables caching entirely. ETags enable conditional requests. The server returns an ETag (a hash of the response body) with the initial response. On subsequent requests, the client sends If-None-Match: ; if the resource has not changed, the server returns 304 Not Modified with no body, saving bandwidth. Last-Modified / If-Modified-Since works similarly but uses timestamps.
Example
# First request — server returns full response + ETag
GET /products/42 HTTP/1.1

HTTP/1.1 200 OK
Content-Type: application/json
ETag: "d41d8cd98f00b204e9800998ecf8427e"
Cache-Control: public, max-age=3600
Last-Modified: Thu, 01 May 2025 10:00:00 GMT

{ "id": 42, "name": "Running Shoes", "price": 89.99 }

# Conditional request — client sends ETag back
GET /products/42 HTTP/1.1
If-None-Match: "d41d8cd98f00b204e9800998ecf8427e"
If-Modified-Since: Thu, 01 May 2025 10:00:00 GMT

# Resource unchanged: 304 (no body, saves bandwidth)
HTTP/1.1 304 Not Modified
ETag: "d41d8cd98f00b204e9800998ecf8427e"

# Resource changed: 200 + new body + new ETag
HTTP/1.1 200 OK
ETag: "new_hash_here"
Content-Type: application/json
{ "id": 42, "name": "Running Shoes Pro", "price": 99.99 }

# Laravel ETag middleware example:
// public function handle($request, Closure $next) {
//   $response = $next($request);
//   if ($request->isMethod('GET') && $response->isOk()) {
//     $etag = md5($response->getContent());
//     $response->setEtag($etag);
//     $response->isNotModified($request); // sets 304 if ETag matches
//   }
//   return $response;
// }