feat(serve-static): respond 304 for If-Modified-Since requests - #396
Open
SynthLuvr wants to merge 3 commits into
Open
feat(serve-static): respond 304 for If-Modified-Since requests#396SynthLuvr wants to merge 3 commits into
SynthLuvr wants to merge 3 commits into
Conversation
serveStatic already sets the Last-Modified header, but never honored a client's If-Modified-Since conditional request. Respond with 304 Not Modified when the file has not been modified since the request date. Per RFC 9110, If-Modified-Since is only evaluated for GET/HEAD, is ignored when If-None-Match is present, and invalid dates are ignored. Dates are compared at second granularity since HTTP dates carry no sub-second precision. The 304 is emitted before any response body branch runs, so no read stream is opened and no Content-Length, Content-Range, or Accept-Ranges headers are set; the check also runs after precompressed variant resolution so the served variant's mtime is used. onFound still fires for 304 responses. Fixes honojs#189
Extract the second-granularity date comparison into an isNotModifiedSince predicate so the handler reads as a single guard clause, and de-duplicate the statSync boilerplate in the If-Modified-Since tests.
A 304 response cannot carry representation metadata, so Content-Type and Content-Encoding are no longer sent alongside it, while Last-Modified and Vary are kept to guide cache updates (RFC 9110 Section 15.4.5). Also covers If-Modified-Since being ignored for methods other than GET/HEAD and for field values with more than one member.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #189
serveStaticnow evaluatesIf-Modified-Sinceper RFC 9110.Last-Modifiedis already set on every response, so this adds only the conditional check:GET/HEADrequests onlyIf-None-Matchis present, as the latter takes precedenceLast-Modified->If-Modified-Sinceround trip match exactly304 Not Modifiedwith an empty body when the file has not changed since the given dateThe check runs after a file (or a precompressed variant, whose own
mtimeis used) has been found and before the response body is built, so a304skipsContent-Length,Accept-Ranges, andContent-Rangewhile still callingonFound. The comparison lives in a smallisNotModifiedSincepredicate so the handler reads as a single guard clause.A
304keepsLast-ModifiedandVarybut dropsContent-TypeandContent-Encoding, since a304cannot carry representation metadata (Section 15.4.5).Varyis retained so caches still know which precompressed representation was selected. This mirrorsremoveContentHeaderFields()insend, used by Express'serve-static.11 tests cover a
304on an exact and on a later date,200on an earlier date, an invalid header,If-None-Matchprecedence, a non-GET/HEADmethod, a field value with more than one member,HEAD, range requests, precompressed variants, andonFound. All offormat,lint,typecheck,test, andbuild+publintpass locally.The author should do the following, if applicable
pnpm run format:fix && pnpm run lint:fixto format the code