diff --git a/pkg/server/staticweb/mount.go b/pkg/server/staticweb/mount.go index 7d309c4..5d025ad 100644 --- a/pkg/server/staticweb/mount.go +++ b/pkg/server/staticweb/mount.go @@ -75,11 +75,21 @@ func (m *mountPoint) ServeHTTP(w http.ResponseWriter, r *http.Request) { fallbackPath := m.fallbackStrategy.GetFallbackPath(filePath) file, err = m.provider.Open(strings.TrimPrefix(fallbackPath, "/")) if err == nil { - // Successfully opened fallback file defer file.Close() m.serveFile(w, r, fallbackPath, file) return } + + // For extensionless paths, also try path/index.html + if path.Ext(filePath) == "" { + indexFallback := path.Join(filePath, "index.html") + file, err = m.provider.Open(strings.TrimPrefix(indexFallback, "/")) + if err == nil { + defer file.Close() + m.serveFile(w, r, indexFallback, file) + return + } + } } // No fallback or fallback failed - return 404 diff --git a/pkg/server/staticweb/policies/fallback.go b/pkg/server/staticweb/policies/fallback.go index 3bdc8b2..55a78bd 100644 --- a/pkg/server/staticweb/policies/fallback.go +++ b/pkg/server/staticweb/policies/fallback.go @@ -49,9 +49,15 @@ func (f *HTMLFallbackStrategy) GetFallbackPath(filePath string) string { return f.indexFile } -// isStaticAsset checks if the path looks like a static asset (has a file extension). +// isStaticAsset checks if the path looks like a static asset (has a non-HTML file extension). +// Paths with no extension are not considered static assets so fallback logic can resolve +// them to path.html or path/index.html. func (f *HTMLFallbackStrategy) isStaticAsset(filePath string) bool { - return path.Ext(filePath) != "" + ext := strings.ToLower(path.Ext(filePath)) + if ext == "" || ext == ".html" || ext == ".htm" { + return false + } + return true } // ExtensionBasedFallback implements a fallback strategy that skips fallback for known static file extensions.