handle error inside serveFile

This commit is contained in:
Mauri de Souza Meneguzzo 2023-12-02 09:34:43 -03:00
parent dbbbe96fd5
commit 7399288d66
2 changed files with 33 additions and 32 deletions

View File

@ -78,15 +78,11 @@ func (d Dir) Open(name string) (File, error) {
if dir == "" {
dir = "."
}
if fi, _ := os.Stat(dir); fi != nil && !fi.IsDir() {
return nil, errors.New("http: attempting to traverse a non-directory")
}
fullName := filepath.Join(dir, path)
f, err := os.Open(fullName)
if err != nil {
return nil, mapOpenError(err, fullName, filepath.Separator, os.Stat)
}
return f, nil
}
@ -664,11 +660,16 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
localRedirect(w, r, path.Base(url)+"/")
return
}
} else {
if url[len(url)-1] == '/' {
localRedirect(w, r, "../"+path.Base(url))
} else if url[len(url)-1] == '/' {
base := path.Base(url)
if base == "/" || base == "." {
// The FileSystem maps a path like "/" or "/./" to a file instead of a directory.
msg := "http: attempting to traverse a non-directory"
Error(w, msg, StatusInternalServerError)
return
}
localRedirect(w, r, "../"+base)
return
}
}

View File

@ -475,6 +475,12 @@ func TestDirJoin(t *testing.T) {
test(Dir("/etc"), "/hosts")
test(Dir("/etc"), "hosts")
test(Dir("/etc"), "../../../../hosts")
// Not really directories, but since we use this trick in
// ServeFile, test it:
test(Dir("/etc/hosts"), "")
test(Dir("/etc/hosts"), "/")
test(Dir("/etc/hosts"), "../")
}
func TestEmptyDirOpenCWD(t *testing.T) {
@ -491,22 +497,6 @@ func TestEmptyDirOpenCWD(t *testing.T) {
test(Dir("./"))
}
// issue 63769
func TestDirNormalFile(t *testing.T) {
test := func(d Dir, filename string) {
f, err := d.Open(filename)
if err == nil {
f.Close()
t.Fatalf("got nil, want error")
}
}
test(Dir("testdata/index.html"), "")
test(Dir("testdata/index.html"), "/")
test(Dir("testdata/index.html"), "..")
test(Dir("testdata/index.html"), "../")
}
func TestServeFileContentType(t *testing.T) { run(t, testServeFileContentType) }
func testServeFileContentType(t *testing.T, mode testMode) {
const ctype = "icecream/chocolate"
@ -1682,15 +1672,25 @@ func (grw gzipResponseWriter) Flush() {
// Issue 63769
func TestFileServerDirWithRootFile(t *testing.T) { run(t, testFileServerDirWithRootFile) }
func testFileServerDirWithRootFile(t *testing.T, mode testMode) {
ts := newClientServerTest(t, mode, FileServer(Dir("testdata/index.html"))).ts
defer ts.Close()
testDirFile := func(t *testing.T, h Handler) {
ts := newClientServerTest(t, mode, h).ts
defer ts.Close()
res, err := ts.Client().Get(ts.URL)
if err != nil {
t.Fatal(err)
res, err := ts.Client().Get(ts.URL)
if err != nil {
t.Fatal(err)
}
if g, w := res.StatusCode, StatusInternalServerError; g != w {
t.Errorf("StatusCode mismatch: got %d, want: %d", g, w)
}
res.Body.Close()
}
if g, w := res.StatusCode, StatusInternalServerError; g != w {
t.Errorf("StatusCode mismatch: got %d, want: %d", g, w)
}
res.Body.Close()
t.Run("FileServer", func(t *testing.T) {
testDirFile(t, FileServer(Dir("testdata/index.html")))
})
t.Run("FileServerFS", func(t *testing.T) {
testDirFile(t, FileServerFS(os.DirFS("testdata/index.html")))
})
}