ETag and HTTP caching
๐ Abstract
The article discusses the use of the HTTP ETag header for client-side caching of GET requests. It explains the caching workflow, how to test it using the GitHub CLI, and how to implement a server that enables client-side caching.
๐ Q&A
[01] Caching the response of a GET endpoint
1. What is the basic workflow for caching the response of a GET endpoint?
- The client makes a GET request to the server.
- The server responds with a 200 OK status, including the content requested and an ETag header.
- The client caches the response and the ETag value.
- For subsequent requests to the same resource, the client includes the If-None-Match header with the ETag value it has cached.
- The server regenerates the ETag independently and checks if the ETag value sent by the client matches the generated one.
- If they match, the server responds with a 304 Not Modified status, indicating that the client's cached version is still valid, and the client serves the resource from the cache.
- If they don't match, the server responds with a 200 OK status, including the new content and a new ETag header, prompting the client to update its cache.
2. What is the significance of the W/ prefix in the ETag header? The W/ prefix indicates that a weak validator is used to validate the content of the cache. Using a weak validator means when the server compares the response payload to generate the hash, it doesn't do it bit-by-bit. So, if the response is JSON, then changing the format of the JSON won't change the value of the ETag header since two JSON payloads with the same content but with different formatting are semantically the same thing.
3. What are the key points to keep in mind when using the If-None-Match header?
- Always wrap your ETag values in double quotes when sending them with the If-None-Match header, as per the specification.
- Using the If-None-Match header to pass the ETag value means that the client request is considered successful when the ETag value from the client doesn't match that of the server. When the values match, the server will return 304 Not Modified with no body.
- When it comes to If-None-Match, the specification tells us to use a weak comparison for ETags. This means that the client will still be able to validate the cache with weak ETags, even if there have been slight changes to the representation of the data.
[02] Writing a server that enables client-side caching
1. How does the example server in Go enable client-side caching for a dynamic GET request?
- The server generates a weak ETag for its content by creating a SHA-256 hash and adding "W/" to the front, indicating it's meant for weak comparison.
- When delivering content, the server includes this weak ETag in the response headers, allowing clients to cache the content along with the ETag.
- For subsequent requests, the server checks if the client has sent an ETag in the If-None-Match header and weakly compares it with the current content's ETag by independently generating the hash.
- If the ETags match, indicating no significant content change, the server replies with a 304 Not Modified status. Otherwise, it sends the content again with a 200 OK status and updates the ETag.
2. What is the importance of ensuring consistent ETag values across multiple servers behind a load balancer? If the servers give out different ETags for the same content, it can mess up how clients cache that content. Clients use ETags to decide if content has changed, and if the ETag value hasn't changed, they know the content is the same and don't download it again, saving bandwidth and speeding up access. But if ETags are inconsistent across servers, clients might download content they already have, wasting bandwidth and slowing things down. This inconsistency also means servers end up dealing with more requests for content that clients could have just used from their cache if ETags were consistent.