diff --git a/backend/backend.go b/backend/backend.go index c757336..8cdcec1 100644 --- a/backend/backend.go +++ b/backend/backend.go @@ -32,7 +32,7 @@ type Backend interface { PutObjectPart(bucket, object, uploadID string, part int, length int64, r io.Reader) (etag string, err error) PutObject(*s3.PutObjectInput) (string, error) - HeadObject(bucket, object string, etag string) (*s3.HeadObjectOutput, error) + HeadObject(bucket, object string) (*s3.HeadObjectOutput, error) GetObject(bucket, object, acceptRange string, startOffset, length int64, writer io.Writer) (*s3.GetObjectOutput, error) GetObjectAcl(bucket, object string) (*s3.GetObjectAclOutput, error) GetObjectAttributes(bucket, object string, attributes []string) (*s3.GetObjectAttributesOutput, error) @@ -131,7 +131,7 @@ func (BackendUnsupported) DeleteObjects(bucket string, objects *s3.DeleteObjects func (BackendUnsupported) GetObject(bucket, object, acceptRange string, startOffset, length int64, writer io.Writer) (*s3.GetObjectOutput, error) { return nil, s3err.GetAPIError(s3err.ErrNotImplemented) } -func (BackendUnsupported) HeadObject(bucket, object string, etag string) (*s3.HeadObjectOutput, error) { +func (BackendUnsupported) HeadObject(bucket, object string) (*s3.HeadObjectOutput, error) { return nil, s3err.GetAPIError(s3err.ErrNotImplemented) } func (BackendUnsupported) GetObjectAcl(bucket, object string) (*s3.GetObjectAclOutput, error) { diff --git a/backend/backend_moq_test.go b/backend/backend_moq_test.go index 5dc73a0..c4c41ec 100644 --- a/backend/backend_moq_test.go +++ b/backend/backend_moq_test.go @@ -65,7 +65,7 @@ var _ Backend = &BackendMock{} // HeadBucketFunc: func(bucket string) (*s3.HeadBucketOutput, error) { // panic("mock out the HeadBucket method") // }, -// HeadObjectFunc: func(bucket string, object string, etag string) (*s3.HeadObjectOutput, error) { +// HeadObjectFunc: func(bucket string, object string) (*s3.HeadObjectOutput, error) { // panic("mock out the HeadObject method") // }, // ListBucketsFunc: func() (*s3.ListBucketsOutput, error) { @@ -172,7 +172,7 @@ type BackendMock struct { HeadBucketFunc func(bucket string) (*s3.HeadBucketOutput, error) // HeadObjectFunc mocks the HeadObject method. - HeadObjectFunc func(bucket string, object string, etag string) (*s3.HeadObjectOutput, error) + HeadObjectFunc func(bucket string, object string) (*s3.HeadObjectOutput, error) // ListBucketsFunc mocks the ListBuckets method. ListBucketsFunc func() (*s3.ListBucketsOutput, error) @@ -350,8 +350,6 @@ type BackendMock struct { Bucket string // Object is the object argument value. Object string - // Etag is the etag argument value. - Etag string } // ListBuckets holds details about calls to the ListBuckets method. ListBuckets []struct { @@ -1082,23 +1080,21 @@ func (mock *BackendMock) HeadBucketCalls() []struct { } // HeadObject calls HeadObjectFunc. -func (mock *BackendMock) HeadObject(bucket string, object string, etag string) (*s3.HeadObjectOutput, error) { +func (mock *BackendMock) HeadObject(bucket string, object string) (*s3.HeadObjectOutput, error) { if mock.HeadObjectFunc == nil { panic("BackendMock.HeadObjectFunc: method is nil but Backend.HeadObject was just called") } callInfo := struct { Bucket string Object string - Etag string }{ Bucket: bucket, Object: object, - Etag: etag, } mock.lockHeadObject.Lock() mock.calls.HeadObject = append(mock.calls.HeadObject, callInfo) mock.lockHeadObject.Unlock() - return mock.HeadObjectFunc(bucket, object, etag) + return mock.HeadObjectFunc(bucket, object) } // HeadObjectCalls gets all the calls that were made to HeadObject. @@ -1108,12 +1104,10 @@ func (mock *BackendMock) HeadObject(bucket string, object string, etag string) ( func (mock *BackendMock) HeadObjectCalls() []struct { Bucket string Object string - Etag string } { var calls []struct { Bucket string Object string - Etag string } mock.lockHeadObject.RLock() calls = mock.calls.HeadObject diff --git a/backend/posix/posix.go b/backend/posix/posix.go index 2f5a29d..62da166 100644 --- a/backend/posix/posix.go +++ b/backend/posix/posix.go @@ -910,7 +910,7 @@ func (p *Posix) GetObject(bucket, object, acceptRange string, startOffset, lengt }, nil } -func (p *Posix) HeadObject(bucket, object string, etag string) (*s3.HeadObjectOutput, error) { +func (p *Posix) HeadObject(bucket, object string) (*s3.HeadObjectOutput, error) { _, err := os.Stat(bucket) if err != nil && errors.Is(err, fs.ErrNotExist) { return nil, s3err.GetAPIError(s3err.ErrNoSuchBucket) @@ -929,10 +929,14 @@ func (p *Posix) HeadObject(bucket, object string, etag string) (*s3.HeadObjectOu } userMetaData := make(map[string]string) - _, contentType, contentEncoding := loadUserMetaData(filepath.Join(bucket, objPath), userMetaData) + _, contentType, contentEncoding := loadUserMetaData(objPath, userMetaData) + + b, err := xattr.Get(objPath, "user.etag") + etag := string(b) + if err != nil { + etag = "" + } - // TODO: fill accept ranges request header? - // TODO: do we need to get etag from xattr? return &s3.HeadObjectOutput{ ContentLength: fi.Size(), ContentType: &contentType, diff --git a/s3api/controllers/backend_moq_test.go b/s3api/controllers/backend_moq_test.go index 2986503..73d60c1 100644 --- a/s3api/controllers/backend_moq_test.go +++ b/s3api/controllers/backend_moq_test.go @@ -66,7 +66,7 @@ var _ backend.Backend = &BackendMock{} // HeadBucketFunc: func(bucket string) (*s3.HeadBucketOutput, error) { // panic("mock out the HeadBucket method") // }, -// HeadObjectFunc: func(bucket string, object string, etag string) (*s3.HeadObjectOutput, error) { +// HeadObjectFunc: func(bucket string, object string) (*s3.HeadObjectOutput, error) { // panic("mock out the HeadObject method") // }, // ListBucketsFunc: func() (*s3.ListBucketsOutput, error) { @@ -173,7 +173,7 @@ type BackendMock struct { HeadBucketFunc func(bucket string) (*s3.HeadBucketOutput, error) // HeadObjectFunc mocks the HeadObject method. - HeadObjectFunc func(bucket string, object string, etag string) (*s3.HeadObjectOutput, error) + HeadObjectFunc func(bucket string, object string) (*s3.HeadObjectOutput, error) // ListBucketsFunc mocks the ListBuckets method. ListBucketsFunc func() (*s3.ListBucketsOutput, error) @@ -351,8 +351,6 @@ type BackendMock struct { Bucket string // Object is the object argument value. Object string - // Etag is the etag argument value. - Etag string } // ListBuckets holds details about calls to the ListBuckets method. ListBuckets []struct { @@ -1083,23 +1081,21 @@ func (mock *BackendMock) HeadBucketCalls() []struct { } // HeadObject calls HeadObjectFunc. -func (mock *BackendMock) HeadObject(bucket string, object string, etag string) (*s3.HeadObjectOutput, error) { +func (mock *BackendMock) HeadObject(bucket string, object string) (*s3.HeadObjectOutput, error) { if mock.HeadObjectFunc == nil { panic("BackendMock.HeadObjectFunc: method is nil but Backend.HeadObject was just called") } callInfo := struct { Bucket string Object string - Etag string }{ Bucket: bucket, Object: object, - Etag: etag, } mock.lockHeadObject.Lock() mock.calls.HeadObject = append(mock.calls.HeadObject, callInfo) mock.lockHeadObject.Unlock() - return mock.HeadObjectFunc(bucket, object, etag) + return mock.HeadObjectFunc(bucket, object) } // HeadObjectCalls gets all the calls that were made to HeadObject. @@ -1109,12 +1105,10 @@ func (mock *BackendMock) HeadObject(bucket string, object string, etag string) ( func (mock *BackendMock) HeadObjectCalls() []struct { Bucket string Object string - Etag string } { var calls []struct { Bucket string Object string - Etag string } mock.lockHeadObject.RLock() calls = mock.calls.HeadObject diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index 5569e52..f9007b1 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -299,7 +299,7 @@ func (c S3ApiController) HeadObject(ctx *fiber.Ctx) error { key = strings.Join([]string{key, keyEnd}, "/") } - res, err := c.be.HeadObject(bucket, key, "") + res, err := c.be.HeadObject(bucket, key) return responce(ctx, res, err) }