Skip to content

rewrite: escape file matcher paths before rewriting#7683

Open
cyphercodes wants to merge 4 commits intocaddyserver:masterfrom
cyphercodes:fix/try-files-escaped-paths
Open

rewrite: escape file matcher paths before rewriting#7683
cyphercodes wants to merge 4 commits intocaddyserver:masterfrom
cyphercodes:fix/try-files-escaped-paths

Conversation

@cyphercodes
Copy link
Copy Markdown
Contributor

Summary

  • Preserve matched file paths containing literal ? and % when try_files rewrites to {http.matchers.file.relative}.
  • Keep file-matcher path placeholders escaped while rewrite parses the target URI, so matched paths are not mistaken for query delimiters or decoded twice.

Fixes #7678

Tests

  • go test ./modules/caddyhttp/fileserver -run TestTryFilesRewriteEscapesMatchedPath -count=1
  • go test ./modules/caddyhttp/rewrite ./modules/caddyhttp/fileserver -count=1

Assistance Disclosure

AI assistance was used for investigation, implementation, and tests. I used Hermes Agent (OpenAI GPT-5.5) and verified the generated changes with the tests above.

Preserve matched file paths containing literal '?' or '%' when try_files rewrites to http.matchers.file.relative.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 2, 2026

CLA assistant check
All committers have signed the CLA.

Comment thread modules/caddyhttp/rewrite/rewrite.go
@cyphercodes
Copy link
Copy Markdown
Contributor Author

Pushed a follow-up to cover the multiple-depth case: the try_files rewrite test now includes an escaped filename under a nested path and creates parent directories for table cases.

Local verification:

  • go test ./modules/caddyhttp/fileserver -run TestTryFilesRewriteEscapesMatchedPath -count=1
  • go test ./modules/caddyhttp/rewrite ./modules/caddyhttp/fileserver -count=1
  • git diff --check

@francislavoie
Copy link
Copy Markdown
Member

I meant a test that covers a request with %2F in the filename not conflicting with nesting.

Also you need to sign the CLA, your commits authored by AI will probably need to be rewritten.

@cyphercodes
Copy link
Copy Markdown
Contributor Author

Pushed a follow-up for the %2F case: the try_files rewrite test now covers a literal nested%2Ffile.html filename while a real nested nested/file.html also exists, so the encoded slash path is verified not to conflict with directory nesting.

Local verification:

  • go test ./modules/caddyhttp/fileserver -run TestTryFilesRewriteEscapesMatchedPath -count=1
  • go test ./modules/caddyhttp/rewrite ./modules/caddyhttp/fileserver -count=1
  • git diff --check

@francislavoie
Copy link
Copy Markdown
Member

We can't accept the changes without the CLA being signed.

@steadytao
Copy link
Copy Markdown
Member

@cyphercodes You must clean and rebase this branch as your AI Agent Hermes Agent pushed a commit with empty identity fields, then review and sign our CLA yourself.

@cyphercodes cyphercodes force-pushed the fix/try-files-escaped-paths branch from ef8e9f6 to 4563a2e Compare May 2, 2026 22:22
@cyphercodes
Copy link
Copy Markdown
Contributor Author

Rewrote the branch metadata so all three commits are authored/committed as cyphercodes <cyphercodes@users.noreply.github.com>.

No source changes were made in this rewrite; it only replaces the previous Hermes Agent <hermes@example.invalid> commit identity so the CLA check can associate the commits with my GitHub account.

@steadytao steadytao requested a review from francislavoie May 2, 2026 22:51
@francislavoie francislavoie added the bug 🐞 Something isn't working label May 3, 2026
@francislavoie francislavoie added this to the v2.11.3 milestone May 3, 2026
Comment thread modules/caddyhttp/rewrite/rewrite.go Outdated
fileMatchRelativePlaceholder := "{http.matchers.file.relative}"
if strings.Contains(path, fileMatchRelativePlaceholder) {
if val, ok := repl.Get("http.matchers.file.relative"); ok {
path = strings.ReplaceAll(path, fileMatchRelativePlaceholder, escapePathPreservingSlashes(fmt.Sprint(val)))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think fmt.Sprint is being used because val is type any, but that's not the right way to do it. The type should be asserted to be string explicitly, not just fed into fmt.Sprint.

@cyphercodes
Copy link
Copy Markdown
Contributor Author

Pushed a follow-up for the latest review: {http.matchers.file.relative} is now only escaped after asserting the replacer value is a string, instead of formatting the any value with fmt.Sprint.

Local verification:

  • go test ./modules/caddyhttp/fileserver -run TestTryFilesRewriteEscapesMatchedPath -count=1
  • go test ./modules/caddyhttp/rewrite ./modules/caddyhttp/fileserver -count=1
  • git diff --check

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

Labels

bug 🐞 Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

try_files mangles paths containing characters like ? and % (whereas file_server without the rewrite works properly)

4 participants