diff --git a/web/file2/fs.go b/web/file2/fs.go index aeb0370..db4f676 100644 --- a/web/file2/fs.go +++ b/web/file2/fs.go @@ -54,9 +54,13 @@ func StoreFromHTTP(fs FS, r *http.Request, key string) error { buf := make([]byte, 512) n, err := file.Read(buf) if err != nil && err != io.EOF { - return err + return fmt.Errorf("read from file: %w", err) } contentType := http.DetectContentType(buf[:n]) + _, err = file.Seek(0, io.SeekStart) + if err != nil { + return fmt.Errorf("seek in file: %w", err) + } i := strings.LastIndexAny(fileHeader.Filename, "/\\") // if i == -1 { i = -1 } diff --git a/web/file2/fs_test.go b/web/file2/fs_test.go index 852a198..98ba2f3 100644 --- a/web/file2/fs_test.go +++ b/web/file2/fs_test.go @@ -1,17 +1,81 @@ package file_test import ( + "errors" "fmt" "io" + "io/fs" + "mime" + "mime/multipart" "net/http" + "net/http/httptest" "os" + "testing" "github.com/google/uuid" + "github.com/stretchr/testify/assert" "dev.sum7.eu/genofire/golang-lib/web/file2" ) -var fs file.FS +type TestFS struct { + assert *assert.Assertions + filename string + data string + contentType string +} + +func (f TestFS) Store(id uuid.UUID, name, contentType string, data io.Reader) error { + f.assert.Equal(f.filename, name) + dat, err := io.ReadAll(data) + f.assert.NoError(err) + f.assert.Equal(f.data, string(dat)) + contentType, _, err = mime.ParseMediaType(contentType) + f.assert.NoError(err) + f.assert.Equal(f.contentType, contentType) + return nil +} + +func (f TestFS) RemoveUUID(id uuid.UUID) error { + return errors.New("TestFS.RemoveUUID called") +} + +func (f TestFS) Open(name string) (fs.File, error) { + return nil, errors.New("TestFS.Open called") +} + +func (f TestFS) OpenUUID(uuid.UUID) (fs.File, error) { + return nil, errors.New("TestFS.OpenUUID called") +} + +func (f TestFS) Check() error { return nil } + +func TestStoreFromHTTP(t *testing.T) { + assert := assert.New(t) + + testfs := TestFS{ + assert: assert, + filename: "cute-cat.png", + data: "content\nof file", + contentType: "text/plain", + } + + r, w := io.Pipe() + m := multipart.NewWriter(w) + rq := httptest.NewRequest("PUT", "/", r) + rq.Header.Set("Content-Type", m.FormDataContentType()) + go func() { + f, err := m.CreateFormFile("file", testfs.filename) + assert.NoError(err) + _, err = f.Write([]byte(testfs.data)) + assert.NoError(err) + m.Close() + }() + + assert.NoError(file.StoreFromHTTP(testfs, rq, "file")) +} + +var fstore file.FS func ExampleFS() { // generate the UUID for the new file @@ -20,13 +84,13 @@ func ExampleFS() { // store a file { f, _ := os.Open("glenda.png") - fs.Store(id, "glenda.png", "image/png", f) + fstore.Store(id, "glenda.png", "image/png", f) f.Close() } // copy back to a local file { - r, _ := fs.OpenUUID(id) + r, _ := fstore.OpenUUID(id) w, _ := os.Create("glenda.png") io.Copy(w, r) r.Close() @@ -36,7 +100,7 @@ func ExampleFS() { func ExampleStoreFromHTTP() { http.HandleFunc("/upload", func(w http.ResponseWriter, r *http.Request) { - if err := file.StoreFromHTTP(fs, r, "file"); err != nil { + if err := file.StoreFromHTTP(fstore, r, "file"); err != nil { w.Header().Set("content-type", "application/json") w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf(`{"message":"%v"}`, err)))