Understanding the 304 Not Modified
Response in HTTP Caching
When developing web applications, efficient resource handling is crucial for performance, especially when it comes to file access and browser caching. One way to optimize this process is by correctly utilizing the 304 Not Modified
HTTP response. This response informs the browser that the resource it requested has not changed since it was last retrieved, allowing the browser to continue using its cached version rather than downloading it again. But how do you know when to send this response? Let’s break it down step by step.
Key HTTP Headers to Check
To determine whether to send a 304 Not Modified
response, you need to check specific HTTP headers sent by the client’s browser. The two main headers to focus on are:
- Etag: This header serves as a unique identifier for a resource at a specific version. The browser compares its cached Etag with the server’s Etag to see if they match.
- If-None-Match: This header is sent by the browser and contains the cached Etag value. If the resource has not changed, the server can respond with
304
.
What to Look For
- If the Etag from the browser exists: If the browser includes either the
Etag
orIf-None-Match
headers in the request, it indicates that it has a previously cached version of the resource. - Quoting Considerations: Browsers sometimes quote the Etag value. Make sure to strip these quotes before comparison.
Necessary Headers for the Initial Response
When initially sending the resource (typically with a 200 OK
response), it’s essential to include relevant headers that inform the browser about the resource state:
- Last-Modified: Indicates the last time the resource was changed. This can be an alternative check for cache validation alongside Etag.
- Etag (as mentioned before): This should be generated for the resource and included in the response headers to facilitate future cache validation.
Implementing the Logic
Here’s a simplified pseudocode example that demonstrates how to implement the logic for sending a 304 Not Modified
response:
server_etag = gen_etag_for_this_file(myfile)
etag_from_browser = get_header("Etag")
if etag_from_browser does not exist:
etag_from_browser = get_header("If-None-Match")
if the browser has quoted the etag:
strip the quotes (e.g. "foo" --> foo)
set server_etag into http header
if etag_from_browser matches server_etag
send 304 return code to browser
Example Server Logic Snippet
Here’s how you might implement this in your server logic:
/* the client should set either Etag or If-None-Match */
mketag(etag, &sb);
etagin = apr_table_get(r->headers_in, "Etag");
if (etagin == NULL)
etagin = apr_table_get(r->headers_in, "If-None-Match");
if (etag != NULL && etag[0] == '"') {
/* Strip quotes if present */
int sl;
sl = strlen(etag);
memmove(etag, etag+1, sl+1);
etag[sl-2] = 0;
}
apr_table_add(r->headers_out, "ETag", etag);
if (etagin != NULL && strcmp(etagin, etag) == 0) {
/* If the etag matches, return a 304 status */
rc = HTTP_NOT_MODIFIED;
}
Final Thoughts
By knowing how and when to send a 304 Not Modified
response, you can effectively reduce server load and improve user experience. Don’t forget about the importance of including the Etag
and Last-Modified
headers during the initial response to allow the client to make accurate cache validation requests later on. If you have questions about Etag generation or need further implementation help, feel free to reach out for more detailed examples. Happy coding!