fix(http): Last-Modified is the file's mtime, not now() - #1427
Draft
vaibhav8a wants to merge 1 commit into
Draft
Conversation
Every static file was served with Last-Modified = SystemTime::now(), so the header advanced by a second between two requests for a file that had not changed. A client doing If-Modified-Since revalidation could never get a meaningful answer and no cache could key on it. FileSystem::modified_at reads the real mtime with the same local-then-database fallback read_file uses, so the timestamp describes the file actually served. DbFsQueries gains a prepared statement for the last_modified column, mirroring the existing was_modified/read_file/exists trio. The header is OMITTED when no mtime is available rather than filled with a guess: a header that says "now" is worse than an absent one, because a client believes it. Both filesystems now compare with `>`. They disagreed - local `>`, DB `>=` - so the same request answered differently depending only on where the file was stored. `>` is the correct half rather than merely the chosen one: If-Modified-Since: T asks whether the file changed AFTER T, so an mtime of exactly T is not a change and must answer 304. I had this as `>=` first and driving the repro caught it - every revalidation re-sent the whole body, which defeats the header this change exists to fix. Verified against the issue's reproduction: mtime reported correctly, stable across requests, and 304/200/304 for If-Modified-Since equal to / older than / newer than the mtime. Fixes sqlpage#1323
lovasoa
marked this pull request as draft
September 2, 2026 21:19
Collaborator
|
Hi @ vaibhav8a ! The above looks like a raw llm output, feel free to edit it to explain your motivation in your own words, what you did and why, then switch the pr back to ready for review. You can explain why and how you used a coding agent, but I'm not accepting pull request that are not human reviewed. |
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.
What
Last-Modifiednow carries the file's real modification time, and both filesystems agree on the comparison.Fixes #1323.
Verified against your reproduction
If-Modified-SinceHow
FileSystem::modified_atreads the mtime through the same local-then-database fallbackread_fileuses, so the timestamp always describes the file actually served.DbFsQueriesgains a prepared statement for thelast_modifiedcolumn, mirroring the existingwas_modified/read_file/existstrio.When no mtime is available the header is omitted rather than filled with a guess — your issue offers that option and I think it is the right one: a header saying "now" is worse than an absent header, because a client believes it.
On the comparison contract:
>, and I got this wrong firstYou said pick one and use it for both. I picked
>=initially, reasoning it was the "safe" side.Driving your reproduction proved that wrong.
If-Modified-Since: Tasks whether the file changed after T, so an mtime of exactly T is not a change and must answer 304. Under>=every revalidation re-sent the whole body — defeating the header this change exists to repair. The304row in the table above was a200until I fixed it.So both sides now use
>, which is the correct half rather than merely the chosen one. The DB query moves from>=to>; local stays>.Scope
I did not add
ETagorCache-Control. Your issue lists them as optional, and they are a separate decision about caching policy rather than a correctness fix — happy to follow up if you want them.Checks
cargo build/cargo check— cleancargo clippy --all-targets— 0 warningscargo fmt --check— cleancargo test --lib— 191 passed(Local tests needed
unixodbcinstalled to link; that is a machine setup detail, not a code change.)