Thanks to visit codestin.com
Credit goes to github.com

Skip to content

serve webdav,http: fix directory Last-Modified using --default-time fallback - fixes #9905 - #9906

Open
sk-sanjay01 wants to merge 1 commit into
rclone:masterfrom
sk-sanjay01:fix-9905-vfs-default-dir-modtime
Open

serve webdav,http: fix directory Last-Modified using --default-time fallback - fixes #9905#9906
sk-sanjay01 wants to merge 1 commit into
rclone:masterfrom
sk-sanjay01:fix-9905-vfs-default-dir-modtime

Conversation

@sk-sanjay01

Copy link
Copy Markdown
Contributor

What does this change do?

Backends without real directory metadata (Swift, S3-style buckets, memory)
list directories as synthesized pseudo-entries with an unknown modtime.
fs.Dir.ModTime() falls back to the configured --default-time (default
2000-01-01) whenever the real modtime is unknown, and this frozen sentinel
was being passed straight through as the Last-Modified header in serve http directory listings, and as the PROPFIND getlastmodified /
OwnCloud lastmodified properties in serve webdav. Because the value
never changes, reverse proxies and WebDAV clients that use Last-Modified
for cache validation see the same date forever and can keep serving stale
directory listings indefinitely.

This makes both servers substitute the current time for the
--default-time sentinel, but only when the entry being served is a
directory — files, and any directory with a real known modtime, are
unaffected.

Repro, verified with and without the fix (using the :memory: backend,
which synthesizes zero-modtime directories the same way Swift/S3 do):

$ rclone serve http :memory: --addr :8080 &
$ echo hi | rclone rcat :memory:subdir/hello.txt
$ curl -I http://localhost:8080/subdir/
Last-Modified: Sat, 01 Jan 2000 00:00:00 GMT   # before the fix
Last-Modified: Fri, 11 Sep 2026 08:22:31 GMT   # after the fix

Testing done:

  • go build ./..., go vet ./..., golangci-lint run ./cmd/serve/http/... ./cmd/serve/webdav/... (0 issues)
  • go test ./cmd/serve/http/... and go test ./cmd/serve/webdav/..., including two new tests using the :memory: backend to reproduce a zero-modtime directory without needing Swift credentials: TestDirectoryListingLastModifiedUnknownModTime (serve http) and TestPROPFINDLastModifiedUnknownModTime (serve webdav, PROPFIND). Both verified to fail on unpatched code and pass with the fix.
  • Live reproduction: built rclone from source, ran rclone serve http :memory: and rclone serve webdav :memory:, uploaded a file into a subdirectory, and confirmed the directory's Last-Modified/getlastmodified value before and after the fix as shown above.

Linked issue

Fixes #9905

Checklist

  • This change is trivial OR it has been discussed and agreed in the linked issue.
  • I have read the contribution guidelines.
  • (If I used AI tools to help write this code) I have read and understood the AI-assisted contributions guidance, and I have tested and take ownership of this change myself.
  • I have added tests for all changes in this PR if appropriate.
  • I have added documentation for the changes if appropriate. (none needed — no flag/option added or changed)
  • All commit messages are in house style.
  • (Backend changes only) test_all passes for this backend... (not applicable — not a backend change)
  • This Pull Request is ready for review.

@ncw

ncw commented Sep 12, 2026

Copy link
Copy Markdown
Member

Testing equality against the default time is a bit untidy.

The fs.Dir objects know whether the time field is set so we could introduce a new field ModTimeValid and type assert for that? That would need to be set as a bool in the vfs.Dir object.

What do you think of that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

With swift backend, rclone serve http provides static Last-Modified to --default-date for directory index

2 participants