Skip to content

Commit aadadb9

Browse files
authored
fs: fix GenerateIndexPages when DirFS or embed.FS is used (#1778)
1 parent 8f5b927 commit aadadb9

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

fs.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,8 @@ func (h *fsHandler) handleRequest(ctx *RequestCtx) {
10681068
mustCompress = false
10691069
ff, err = h.openFSFile(filePath, mustCompress, fileEncoding)
10701070
}
1071-
if err == errDirIndexRequired {
1071+
1072+
if errors.Is(err, errDirIndexRequired) {
10721073
if !hasTrailingSlash {
10731074
ctx.RedirectBytes(append(path, '/'), StatusFound)
10741075
return
@@ -1261,6 +1262,11 @@ func (h *fsHandler) createDirIndex(ctx *RequestCtx, dirPath string, mustCompress
12611262

12621263
base := ctx.URI()
12631264

1265+
// io/fs doesn't support ReadDir with empty path.
1266+
if dirPath == "" {
1267+
dirPath = "."
1268+
}
1269+
12641270
basePathEscaped := html.EscapeString(string(base.Path()))
12651271
_, _ = fmt.Fprintf(w, "<html><head><title>%s</title><style>.dir { font-weight: bold }</style></head><body>", basePathEscaped)
12661272
_, _ = fmt.Fprintf(w, "<h1>%s</h1>", basePathEscaped)
@@ -1556,12 +1562,17 @@ func (h *fsHandler) openFSFile(filePath string, mustCompress bool, fileEncoding
15561562
if mustCompress {
15571563
filePath += h.compressedFileSuffixes[fileEncoding]
15581564
}
1559-
15601565
f, err := h.filesystem.Open(filePath)
15611566
if err != nil {
15621567
if mustCompress && errors.Is(err, fs.ErrNotExist) {
15631568
return h.compressAndOpenFSFile(filePathOriginal, fileEncoding)
15641569
}
1570+
1571+
// If the file is not found and the path is empty, let's return errDirIndexRequired error.
1572+
if filePath == "" && (errors.Is(err, fs.ErrNotExist) || errors.Is(err, fs.ErrInvalid)) {
1573+
return nil, errDirIndexRequired
1574+
}
1575+
15651576
return nil, err
15661577
}
15671578

fs_fs_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,3 +636,85 @@ func TestDirFSServeFileDirectoryRedirect(t *testing.T) {
636636
t.Fatalf("Unexpected status code %d for file '/fs.go'. Expecting %d.", ctx.Response.StatusCode(), StatusOK)
637637
}
638638
}
639+
640+
func TestFSFSGenerateIndexOsDirFS(t *testing.T) {
641+
t.Parallel()
642+
643+
t.Run("dirFS", func(t *testing.T) {
644+
t.Parallel()
645+
646+
fs := &FS{
647+
FS: dirTestFilesystem,
648+
Root: ".",
649+
GenerateIndexPages: true,
650+
}
651+
h := fs.NewRequestHandler()
652+
653+
var ctx RequestCtx
654+
var req Request
655+
ctx.Init(&req, nil, nil)
656+
657+
h(&ctx)
658+
659+
cases := []string{"/", "//", ""}
660+
for _, c := range cases {
661+
ctx.Request.Reset()
662+
ctx.Response.Reset()
663+
664+
req.Header.SetMethod(MethodGet)
665+
req.SetRequestURI("http://foobar.com" + c)
666+
h(&ctx)
667+
668+
if ctx.Response.StatusCode() != StatusOK {
669+
t.Fatalf("unexpected status code %d for path %q. Expecting %d", ctx.Response.StatusCode(), ctx.Response.StatusCode(), StatusOK)
670+
}
671+
672+
if !bytes.Contains(ctx.Response.Body(), []byte("fasthttputil")) {
673+
t.Fatalf("unexpected body %q. Expecting to contain %q", ctx.Response.Body(), "fasthttputil")
674+
}
675+
676+
if !bytes.Contains(ctx.Response.Body(), []byte("fs.go")) {
677+
t.Fatalf("unexpected body %q. Expecting to contain %q", ctx.Response.Body(), "fs.go")
678+
}
679+
}
680+
})
681+
682+
t.Run("embedFS", func(t *testing.T) {
683+
t.Parallel()
684+
685+
fs := &FS{
686+
FS: fsTestFilesystem,
687+
Root: ".",
688+
GenerateIndexPages: true,
689+
}
690+
h := fs.NewRequestHandler()
691+
692+
var ctx RequestCtx
693+
var req Request
694+
ctx.Init(&req, nil, nil)
695+
696+
h(&ctx)
697+
698+
cases := []string{"/", "//", ""}
699+
for _, c := range cases {
700+
ctx.Request.Reset()
701+
ctx.Response.Reset()
702+
703+
req.Header.SetMethod(MethodGet)
704+
req.SetRequestURI("http://foobar.com" + c)
705+
h(&ctx)
706+
707+
if ctx.Response.StatusCode() != StatusOK {
708+
t.Fatalf("unexpected status code %d for path %q. Expecting %d", ctx.Response.StatusCode(), ctx.Response.StatusCode(), StatusOK)
709+
}
710+
711+
if !bytes.Contains(ctx.Response.Body(), []byte("fasthttputil")) {
712+
t.Fatalf("unexpected body %q. Expecting to contain %q", ctx.Response.Body(), "fasthttputil")
713+
}
714+
715+
if !bytes.Contains(ctx.Response.Body(), []byte("fs.go")) {
716+
t.Fatalf("unexpected body %q. Expecting to contain %q", ctx.Response.Body(), "fs.go")
717+
}
718+
}
719+
})
720+
}

0 commit comments

Comments
 (0)