-
-
Notifications
You must be signed in to change notification settings - Fork 2k
🐛 bug: Fix Static middleware browser support for subdirectories #3673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| h1 { | ||
| color: black; | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,6 +23,9 @@ import ( | |||||||||
| // It returns an error if the path attempts to traverse directories. | ||||||||||
| func sanitizePath(p []byte, filesystem fs.FS) ([]byte, error) { | ||||||||||
| var s string | ||||||||||
|
|
||||||||||
| hasTrailingSlash := len(p) > 0 && p[len(p)-1] == '/' | ||||||||||
|
|
||||||||||
|
Comment on lines
+27
to
+28
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainPreserve trailing slash from the original request, not from the rewritten path PathRewrite appends a trailing slash to the working path unconditionally in the default branch. Because hasTrailingSlash is computed from p inside sanitizePath (after that rewrite), it will be true for most non-root requests, including file paths. This means sanitizePath will also append a trailing slash post-clean, producing paths like /style.css/ even when the original request was /style.css. While fasthttp.FS appears to tolerate this (tests pass), it diverges from the stated intent “preserve the original trailing slash” and risks subtle inconsistencies or future regressions. Recommended refactor:
Pros:
Cons:
Suggested changes:
- hasTrailingSlash := len(p) > 0 && p[len(p)-1] == '/'
+ // trailing slash preservation is handled by the caller (based on original request)- if hasTrailingSlash && len(s) > 1 && s[len(s)-1] != '/' {
- s += "/"
- }
+ // caller may re-append a trailing slash after validation/cleaning
Go (outside the changed ranges; illustrative patch): fs.PathRewrite = func(fctx *fasthttp.RequestCtx) []byte {
raw := fctx.Path() // original request path
reqHasTrailingSlash := len(raw) > 0 && raw[len(raw)-1] == '/'
path := fctx.Path()
// ... existing prefix handling and default-case adjustments ...
// (keep current logic that ensures leading slash etc.)
sanitized, err := sanitizePath(path, fs.FS)
if err != nil {
return []byte("/__fiber_invalid__")
}
if reqHasTrailingSlash && len(sanitized) > 1 && sanitized[len(sanitized)-1] != '/' {
sanitized = append(sanitized, '/')
}
return sanitized
}This ensures trailing slashes are preserved only when they existed on the client’s request. To confirm sanitizePath isn’t used elsewhere in a way that would need updating: Add a short comment explaining why trailing slash is preserved (fasthttp FS directory handling), and why it’s done post-clean to avoid invalid fs.ValidPath(".../"). Also applies to: 72-74 🏁 Script executed: #!/bin/bash
# Find all sanitizePath call sites and their contexts
rg -n --no-heading "sanitizePath\\(" -A 3 -B 3
# Inspect rewrite code to verify trailing slash appending occurs pre-sanitize
rg -n --no-heading "PathRewrite\\s*=\\s*func\\(" -A 120 | sed -n '1,200p'Length of output: 8863 🏁 Script executed: #!/bin/bash
# Display the full sanitizePath implementation for review
sed -n '1,120p' middleware/static/static.goLength of output: 2546 Preserve the client’s original trailing-slash, not the one injected by PathRewrite Currently, PathRewrite unconditionally appends “/” whenever it strips the route prefix for directories, which makes Key locations to update:
Suggested diffs: --- a/middleware/static/static.go
+++ b/middleware/static/static.go
@@ func sanitizePath(p []byte, filesystem fs.FS) ([]byte, error) {
- hasTrailingSlash := len(p) > 0 && p[len(p)-1] == '/'
…
- if hasTrailingSlash && len(s) > 1 && s[len(s)-1] != '/' {
- s += "/"
- }
+ // trailing-slash preservation is handled by PathRewrite (caller) based on the original request--- a/middleware/static/static.go
+++ b/middleware/static/static.go
@@ fs.PathRewrite = func(fctx *fasthttp.RequestCtx) []byte {
- path := fctx.Path()
+ raw := fctx.Path()
+ reqHasSlash := len(raw) > 0 && raw[len(raw)-1] == '/'
path := raw
… // existing prefixLogic
// default (non-file) branch:
- if len(path) == 0 || path[len(path)-1] != '/' {
- path = append(path, '/')
- }
+ // do not append here; sanitizePath will clean, and we’ll re-append below--- a/middleware/static/static.go
+++ b/middleware/static/static.go
@@ fs.PathRewrite = func(fctx *fasthttp.RequestCtx) []byte {
sanitized, err := sanitizePath(path, fs.FS)
if err != nil {
return []byte("/__fiber_invalid__")
}
+ if reqHasSlash && len(sanitized) > 1 && sanitized[len(sanitized)-1] != '/' {
+ sanitized = append(sanitized, '/')
+ }
return sanitized
}These changes will: 🤖 Prompt for AI Agents |
||||||||||
| if bytes.IndexByte(p, '\\') >= 0 { | ||||||||||
| b := make([]byte, len(p)) | ||||||||||
| copy(b, p) | ||||||||||
|
|
@@ -66,6 +69,10 @@ func sanitizePath(p []byte, filesystem fs.FS) ([]byte, error) { | |||||||||
| s = "/" + s | ||||||||||
| } | ||||||||||
|
|
||||||||||
|
||||||||||
| // Only add a trailing slash if the path is not the root "/". | |
| // This prevents turning "/" into "//". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Consider extracting the trailing slash check into a named constant or helper function for better readability and reusability.