From 48a3dc0bd95bae4246e1d622e699cbadb491daae Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Wed, 3 Jan 2018 16:34:20 -0600 Subject: [PATCH] error on virtual directory that does not exist On the first call to find(), index the directories in the box. When returning a virtual directory, first check to see if that directory exists, if not return a not found error. This will cause http.FileServer to return a 404 on a directory that does not exist in the box. --- box.go | 29 +++++++++++++++++++++++++---- box_test.go | 12 ++++++++++-- packr_test.go | 1 + 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/box.go b/box.go index aff0582..d5242e7 100644 --- a/box.go +++ b/box.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "net/http" "os" + "path" "path/filepath" "runtime" "strings" @@ -45,9 +46,10 @@ func NewBox(path string) Box { // Box represent a folder on a disk you want to // have access to in the built Go binary. type Box struct { - Path string - callingDir string - data map[string][]byte + Path string + callingDir string + data map[string][]byte + directories map[string]bool } // String of the file asked for or an empty string. @@ -102,6 +104,10 @@ func (b Box) decompress(bb []byte) []byte { } func (b Box) find(name string) (File, error) { + if b.directories == nil { + b.indexDirectories() + } + cleanName := filepath.ToSlash(filepath.Clean(name)) // Ensure name is not outside the box if strings.HasPrefix(cleanName, "../") { @@ -121,7 +127,10 @@ func (b Box) find(name string) (File, error) { // returns http.StatusNotFound instead of http.StatusInternalServerError. return nil, os.ErrNotExist } - return newVirtualDir(cleanName), nil + if _, ok := b.directories[cleanName]; ok { + return newVirtualDir(cleanName), nil + } + return nil, os.ErrNotExist } // Not found in the box virtual fs, try to get it from the file system @@ -187,3 +196,15 @@ func (b Box) List() []string { } return keys } + +func (b *Box) indexDirectories() { + b.directories = map[string]bool{} + if _, ok := data[b.Path]; ok { + for name, _ := range data[b.Path] { + prefix, _ := path.Split(name) + // Even on Windows the suffix appears to be a / + prefix = strings.TrimSuffix(prefix, "/") + b.directories[prefix] = true + } + } +} diff --git a/box_test.go b/box_test.go index 01c6e07..9b8316b 100644 --- a/box_test.go +++ b/box_test.go @@ -61,12 +61,12 @@ func Test_Box_Walk_Virtual(t *testing.T) { return nil }) r.NoError(err) - r.Equal(3, count) + r.Equal(4, count) } func Test_List_Virtual(t *testing.T) { r := require.New(t) - mustHave := []string{"a", "b", "c"} + mustHave := []string{"a", "b", "c", "d/a"} actual := virtualBox.List() sort.Strings(actual) r.Equal(mustHave, actual) @@ -115,3 +115,11 @@ func Test_Box_find(t *testing.T) { }) } } + +func Test_Virtual_Directory_Not_Found(t *testing.T) { + r := require.New(t) + _, err := virtualBox.find("d") + r.NoError(err) + _, err = virtualBox.find("does-not-exist") + r.Error(err) +} \ No newline at end of file diff --git a/packr_test.go b/packr_test.go index 90eca18..a6132cd 100644 --- a/packr_test.go +++ b/packr_test.go @@ -14,6 +14,7 @@ func init() { PackBytes(virtualBox.Path, "a", []byte("a")) PackBytes(virtualBox.Path, "b", []byte("b")) PackBytes(virtualBox.Path, "c", []byte("c")) + PackBytes(virtualBox.Path, "d/a", []byte("d/a")) } func Test_PackBytes(t *testing.T) {