== How ETags and If-Modified-Since headers interact Part of the fun of writing programs that deal with HTTP is decoding things like [[RFC 2616|http://www.w3.org/Protocols/rfc2616/rfc2616.html]] to answer somewhat obscure questions about how various things interact. Today's case is the following question: > When can your web server generate a 304 'content not modified' > response if it receives a request with both an _If-None-Match_ and > an _If-Modified-Since_ header? _If-None-Match_ and _If-Modified-Since_ are HTTP request headers used to implement 'conditional GET', a bandwidth saving technique that avoids re-fetching unchanged pages (see [[here|http://fishbowl.pastiche.org/2002/10/21/http_conditional_get_for_rss_hackers]] or [[here|http://www.hecker.org/blosxom/validating-and-caching]] for more discussion of this). (_ETag_ headers come into this because the server's _ETag_ value is what the client will use as its _If-None-Match_ value in the conditional GET request.) The answer turns out to be in section [[13.3.4|http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.4]] of [[RFC 2616]]. It is (de-RFC-ized): > You can only generate a 304 response if both headers match; the > _If-None-Match_ matches the response's _ETag_ *and* the > _If-Modified-Since_ header matches the _Last-Modified_. In the case of _If-Modified-Since_ and _Last-Modified_, servers may require an exact match instead of merely Last-Modified being no later than If-Modified-Since. As [[RFC 2616]] notes in [[14.25|http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25]], client authors should really just store the Last-Modified result as a string and hork it up in their If-Modified-Since header. This came up when I threw debugging code into DWiki to see exactly what various people repeatedly pulling my Atom feed without getting bandwidth-efficient 304 responses were sending. One feed reader was sending both headers but making up their own If-Modified-Since instead of just repeating Last-Modified. (DWiki requires an exact match for technical reasons.) (Whether by accident or by reading [[RFC 2616]] carefully when I wrote the code and then forgetting it, DWiki does the right thing when both headers are present.)