diff --git a/handler.go b/handler.go index 772dd54..e22e1c0 100644 --- a/handler.go +++ b/handler.go @@ -102,13 +102,13 @@ func (h *UploadAssetHandler) Read(s ssh.Session, entry *utils.FileEntry) (os.Fil if err != nil { return nil, nil, err } - contents, size, modTime, err := h.Cfg.Storage.GetObject(bucket, fname) + contents, info, err := h.Cfg.Storage.GetObject(bucket, fname) if err != nil { return nil, nil, err } - fileInfo.FSize = size - fileInfo.FModTime = modTime + fileInfo.FSize = info.Size + fileInfo.FModTime = info.LastModified reader := NewAllReaderAt(contents) diff --git a/storage/fs.go b/storage/fs.go index e52e831..822cf33 100644 --- a/storage/fs.go +++ b/storage/fs.go @@ -87,18 +87,26 @@ func (s *StorageFS) DeleteBucket(bucket Bucket) error { return os.RemoveAll(bucket.Path) } -func (s *StorageFS) GetObject(bucket Bucket, fpath string) (utils.ReaderAtCloser, int64, time.Time, error) { +func (s *StorageFS) GetObject(bucket Bucket, fpath string) (utils.ReaderAtCloser, *ObjectInfo, error) { + objInfo := &ObjectInfo{ + LastModified: time.Time{}, + Metadata: nil, + UserMetadata: map[string]string{}, + } + dat, err := os.Open(filepath.Join(bucket.Path, fpath)) if err != nil { - return nil, 0, time.Time{}, err + return nil, objInfo, err } info, err := dat.Stat() if err != nil { - return nil, 0, time.Time{}, err + return nil, objInfo, err } - return dat, info.Size(), info.ModTime(), nil + objInfo.Size = info.Size() + objInfo.LastModified = info.ModTime() + return dat, objInfo, nil } func (s *StorageFS) PutObject(bucket Bucket, fpath string, contents io.Reader, entry *utils.FileEntry) (string, int64, error) { diff --git a/storage/minio.go b/storage/minio.go index aca1969..ca2ba05 100644 --- a/storage/minio.go +++ b/storage/minio.go @@ -152,29 +152,37 @@ func (s *StorageMinio) DeleteBucket(bucket Bucket) error { return s.Client.RemoveBucket(context.TODO(), bucket.Name) } -func (s *StorageMinio) GetObject(bucket Bucket, fpath string) (utils.ReaderAtCloser, int64, time.Time, error) { - modTime := time.Time{} +func (s *StorageMinio) GetObject(bucket Bucket, fpath string) (utils.ReaderAtCloser, *ObjectInfo, error) { + objInfo := &ObjectInfo{ + Size: 0, + LastModified: time.Time{}, + ETag: "", + } info, err := s.Client.StatObject(context.Background(), bucket.Name, fpath, minio.StatObjectOptions{}) if err != nil { - return nil, 0, modTime, err + return nil, objInfo, err } - modTime = info.LastModified + objInfo.LastModified = info.LastModified + objInfo.Metadata = info.Metadata + objInfo.UserMetadata = info.UserMetadata obj, err := s.Client.GetObject(context.Background(), bucket.Name, fpath, minio.GetObjectOptions{}) if err != nil { - return nil, 0, modTime, err + return nil, objInfo, err } if mtime, ok := info.UserMetadata["Mtime"]; ok { mtimeUnix, err := strconv.Atoi(mtime) if err == nil { - modTime = time.Unix(int64(mtimeUnix), 0) + objInfo.LastModified = time.Unix(int64(mtimeUnix), 0) } } - return obj, info.Size, modTime, nil + objInfo.Size = info.Size + + return obj, objInfo, nil } func (s *StorageMinio) PutObject(bucket Bucket, fpath string, contents io.Reader, entry *utils.FileEntry) (string, int64, error) { diff --git a/storage/s3.go b/storage/s3.go index 3118161..159be0c 100644 --- a/storage/s3.go +++ b/storage/s3.go @@ -207,23 +207,33 @@ func (s *StorageS3) DeleteBucket(bucket Bucket) error { return err } -func (s *StorageS3) GetObject(bucket Bucket, fpath string) (utils.ReaderAtCloser, int64, time.Time, error) { - modTime := time.Time{} +func (s *StorageS3) GetObject(bucket Bucket, fpath string) (utils.ReaderAtCloser, *ObjectInfo, error) { input := &s3.GetObjectInput{ Bucket: aws.String(bucket.Name), Key: aws.String(fpath), } + objInfo := &ObjectInfo{ + LastModified: time.Time{}, + Metadata: nil, + UserMetadata: map[string]string{}, + } + result, err := s.Client.GetObject(context.TODO(), input) if err != nil { - return nil, 0, modTime, err + return nil, objInfo, err } + objInfo.UserMetadata = result.Metadata + objInfo.ETag = *result.ETag + objInfo.Size = *result.ContentLength + objInfo.LastModified = *result.LastModified + // unfortunately we have to read the object into memory because we // require io.ReadAt data, err := io.ReadAll(result.Body) if err != nil { - return nil, *result.ContentLength, modTime, err + return nil, objInfo, err } defer result.Body.Close() @@ -231,7 +241,7 @@ func (s *StorageS3) GetObject(bucket Bucket, fpath string) (utils.ReaderAtCloser body := bytes.NewReader(data) content := utils.NopReaderAtCloser(body) - return content, *result.ContentLength, *result.LastModified, nil + return content, objInfo, nil } func (s *StorageS3) PutObject(bucket Bucket, fpath string, contents io.Reader, entry *utils.FileEntry) (string, int64, error) { diff --git a/storage/storage.go b/storage/storage.go index 2d13401..1809514 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -2,6 +2,7 @@ package storage import ( "io" + "net/http" "os" "time" @@ -21,8 +22,16 @@ type ObjectStorage interface { ListBuckets() ([]string, error) DeleteBucket(bucket Bucket) error - GetObject(bucket Bucket, fpath string) (utils.ReaderAtCloser, int64, time.Time, error) + GetObject(bucket Bucket, fpath string) (utils.ReaderAtCloser, *ObjectInfo, error) PutObject(bucket Bucket, fpath string, contents io.Reader, entry *utils.FileEntry) (string, int64, error) DeleteObject(bucket Bucket, fpath string) error ListObjects(bucket Bucket, dir string, recursive bool) ([]os.FileInfo, error) } + +type ObjectInfo struct { + Size int64 + LastModified time.Time + ETag string + Metadata http.Header + UserMetadata map[string]string +}