Note that the newer "RFC 7232 Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests" has a section on precedence which changes how this behaviour is specified. This effectively says that If-None-Match
takes precedence over If-Modified-Since
. See:
3. When If-None-Match is present, evaluate the If-None-Match
precondition:
* if true, continue to step 5
* if false for GET/HEAD, respond 304 (Not Modified)
* if false for other methods, respond 412 (Precondition Failed)
4. When the method is GET or HEAD, If-None-Match is not present, and
If-Modified-Since is present, evaluate the If-Modified-Since
precondition:
* if true, continue to step 5
* if false, respond 304 (Not Modified)
5. When the method is GET and both Range and If-Range are present,
evaluate the If-Range precondition:
* if the validator matches and the Range specification is
applicable to the selected representation, respond 206
(Partial Content) [RFC7233]
6. Otherwise,
* all conditions are met, so perform the requested action and
respond according to its success or failure.
See here how step 3. causes an evaluation of the If-None-Match
pre-condition, and if it is present then you never go to step 4. which is the step that evaluates If-Modified-Since
.