xl,fs: Return 404 if object ends with a separator (#3897)

HEAD Object for FS and XL was returning invalid object name when
an object name has a trailing slash separator, this PR changes the
behavior and will always return 404 object not found, this guarantees
a better compatibility with S3 spec.
master
Anis Elleuch 8 years ago committed by Harshavardhana
parent 5f7565762e
commit a5e60706a2
  1. 6
      cmd/fs-v1.go
  2. 40
      cmd/object_api_suite_test.go
  3. 6
      cmd/xl-v1-object.go

@ -470,6 +470,12 @@ func (fs fsObjects) getObjectInfo(bucket, object string) (ObjectInfo, error) {
// GetObjectInfo - reads object metadata and replies back ObjectInfo. // GetObjectInfo - reads object metadata and replies back ObjectInfo.
func (fs fsObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) { func (fs fsObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) {
// This is a special case with object whose name ends with
// a slash separator, we always return object not found here.
if hasSuffix(object, slashSeparator) {
return ObjectInfo{}, toObjectErr(traceError(errFileNotFound), bucket, object)
}
if err := checkGetObjArgs(bucket, object); err != nil { if err := checkGetObjArgs(bucket, object); err != nil {
return ObjectInfo{}, err return ObjectInfo{}, err
} }

@ -735,12 +735,13 @@ func (s *ObjectLayerAPISuite) TestGetDirectoryReturnsObjectNotFound(c *C) {
// Tests validate that GetObject on an existing directory fails as expected. // Tests validate that GetObject on an existing directory fails as expected.
func testGetDirectoryReturnsObjectNotFound(obj ObjectLayer, instanceType string, c TestErrHandler) { func testGetDirectoryReturnsObjectNotFound(obj ObjectLayer, instanceType string, c TestErrHandler) {
err := obj.MakeBucket("bucket") bucketName := "bucket"
err := obj.MakeBucket(bucketName)
if err != nil { if err != nil {
c.Fatalf("%s: <ERROR> %s", instanceType, err) c.Fatalf("%s: <ERROR> %s", instanceType, err)
} }
_, err = obj.PutObject("bucket", "dir1/dir3/object", _, err = obj.PutObject(bucketName, "dir1/dir3/object",
int64(len("The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed.")), int64(len("The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed.")),
bytes.NewBufferString("One or more of the specified parts could not be found. The part might not have been uploaded, or the specified entity tag might not have matched the part's entity tag."), nil, "") bytes.NewBufferString("One or more of the specified parts could not be found. The part might not have been uploaded, or the specified entity tag might not have matched the part's entity tag."), nil, "")
@ -748,42 +749,25 @@ func testGetDirectoryReturnsObjectNotFound(obj ObjectLayer, instanceType string,
c.Fatalf("%s: <ERROR> %s", instanceType, err) c.Fatalf("%s: <ERROR> %s", instanceType, err)
} }
_, err = obj.GetObjectInfo("bucket", "dir1") for i, objName := range []string{"dir1", "dir1/", "dir1/dir3", "dir1/dir3/"} {
_, err = obj.GetObjectInfo(bucketName, objName)
if isErrObjectNotFound(err) { if isErrObjectNotFound(err) {
err = errorCause(err) err = errorCause(err)
err1 := err.(ObjectNotFound) err1 := err.(ObjectNotFound)
if err1.Bucket != "bucket" { if err1.Bucket != bucketName {
c.Errorf("%s: Expected the bucket name in the error message to be `%s`, but instead found `%s`", c.Errorf("Test %d, %s: Expected the bucket name in the error message to be `%s`, but instead found `%s`",
instanceType, "bucket", err1.Bucket) i+1, instanceType, bucketName, err1.Bucket)
} }
if err1.Object != "dir1" { if err1.Object != objName {
c.Errorf("%s: Expected the object name in the error message to be `%s`, but instead found `%s`", c.Errorf("Test %d, %s: Expected the object name in the error message to be `%s`, but instead found `%s`",
instanceType, "dir1", err1.Object) i+1, instanceType, objName, err1.Object)
} }
} else { } else {
if err.Error() != "ObjectNotFound" { if err.Error() != "ObjectNotFound" {
c.Errorf("%s: Expected the error message to be `%s`, but instead found `%s`", instanceType, c.Errorf("Test %d, %s: Expected the error message to be `%s`, but instead found `%s`", i+1, instanceType,
"ObjectNotFound", err.Error()) "ObjectNotFound", err.Error())
} }
} }
_, err = obj.GetObjectInfo("bucket", "dir1/")
if isErrObjectNameInvalid(err) {
err = errorCause(err)
err1 := err.(ObjectNameInvalid)
if err1.Bucket != "bucket" {
c.Errorf("%s: Expected the bucket name in the error message to be `%s`, but instead found `%s`",
instanceType, "bucket", err1.Bucket)
}
if err1.Object != "dir1/" {
c.Errorf("%s: Expected the object name in the error message to be `%s`, but instead found `%s`",
instanceType, "dir1/", err1.Object)
}
} else {
// force a failure with a line number.
if err.Error() != "ObjectNotFound" {
c.Errorf("%s: Expected the error message to be `%s`, but instead found `%s`", instanceType, "ObjectNotFound", err.Error())
}
} }
} }

@ -321,6 +321,12 @@ func (xl xlObjects) GetObject(bucket, object string, startOffset int64, length i
// GetObjectInfo - reads object metadata and replies back ObjectInfo. // GetObjectInfo - reads object metadata and replies back ObjectInfo.
func (xl xlObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) { func (xl xlObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) {
// This is a special case with object whose name ends with
// a slash separator, we always return object not found here.
if hasSuffix(object, slashSeparator) {
return ObjectInfo{}, toObjectErr(traceError(errFileNotFound), bucket, object)
}
if err := checkGetObjArgs(bucket, object); err != nil { if err := checkGetObjArgs(bucket, object); err != nil {
return ObjectInfo{}, err return ObjectInfo{}, err
} }

Loading…
Cancel
Save