mirror of
https://github.com/versity/versitygw.git
synced 2026-04-16 19:06:58 +00:00
fix: Fixed CopyObject copy-source parsing to handle object names with special characters
This commit is contained in:
@@ -116,15 +116,13 @@ func ParseCopySource(copySourceHeader string) (string, string, string, error) {
|
||||
copySourceHeader = copySourceHeader[1:]
|
||||
}
|
||||
|
||||
cSplitted := strings.Split(copySourceHeader, "?")
|
||||
copySource := cSplitted[0]
|
||||
var versionId string
|
||||
if len(cSplitted) > 1 {
|
||||
versionIdParts := strings.Split(cSplitted[1], "=")
|
||||
if len(versionIdParts) != 2 || versionIdParts[0] != "versionId" {
|
||||
return "", "", "", s3err.GetAPIError(s3err.ErrInvalidRequest)
|
||||
}
|
||||
versionId = versionIdParts[1]
|
||||
var copySource, versionId string
|
||||
i := strings.LastIndex(copySourceHeader, "?versionId=")
|
||||
if i == -1 {
|
||||
copySource = copySourceHeader
|
||||
} else {
|
||||
copySource = copySourceHeader[:i]
|
||||
versionId = copySourceHeader[i+11:]
|
||||
}
|
||||
|
||||
srcBucket, srcObject, ok := strings.Cut(copySource, "/")
|
||||
|
||||
@@ -356,7 +356,7 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
},
|
||||
ErrInvalidAccessKeyID: {
|
||||
Code: "InvalidAccessKeyId",
|
||||
Description: "The access key ID you provided does not exist in our records.",
|
||||
Description: "The AWS Access Key Id you provided does not exist in our records.",
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
},
|
||||
ErrRequestNotReadyYet: {
|
||||
|
||||
@@ -528,6 +528,7 @@ func TestVersioning(s *S3Conf) {
|
||||
Versioning_CopyObject_success(s)
|
||||
Versioning_CopyObject_non_existing_version_id(s)
|
||||
Versioning_CopyObject_from_an_object_version(s)
|
||||
Versioning_CopyObject_special_chars(s)
|
||||
// HeadObject action
|
||||
Versioning_HeadObject_invalid_versionId(s)
|
||||
Versioning_HeadObject_success(s)
|
||||
@@ -895,6 +896,7 @@ func GetIntTests() IntTests {
|
||||
"Versioning_CopyObject_success": Versioning_CopyObject_success,
|
||||
"Versioning_CopyObject_non_existing_version_id": Versioning_CopyObject_non_existing_version_id,
|
||||
"Versioning_CopyObject_from_an_object_version": Versioning_CopyObject_from_an_object_version,
|
||||
"Versioning_CopyObject_special_chars": Versioning_CopyObject_special_chars,
|
||||
"Versioning_HeadObject_invalid_versionId": Versioning_HeadObject_invalid_versionId,
|
||||
"Versioning_HeadObject_success": Versioning_HeadObject_success,
|
||||
"Versioning_HeadObject_delete_marker": Versioning_HeadObject_delete_marker,
|
||||
|
||||
@@ -10673,6 +10673,59 @@ func Versioning_CopyObject_from_an_object_version(s *S3Conf) error {
|
||||
}, withVersioning())
|
||||
}
|
||||
|
||||
func Versioning_CopyObject_special_chars(s *S3Conf) error {
|
||||
testName := "Versioning_CopyObject_special_chars"
|
||||
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
|
||||
srcObj, dstBucket, dstObj := "foo?bar", getBucketName(), "bar&foo"
|
||||
err := setup(s, dstBucket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srcObjVersions, err := createObjVersions(s3client, bucket, srcObj, 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srcObjVersionId := *srcObjVersions[0].VersionId
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
res, err := s3client.CopyObject(ctx, &s3.CopyObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &dstObj,
|
||||
CopySource: getPtr(fmt.Sprintf("%v/%v?versionId=%v", bucket, srcObj, srcObjVersionId)),
|
||||
})
|
||||
cancel()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if res.VersionId == nil || *res.VersionId == "" {
|
||||
return fmt.Errorf("expected non empty versionId")
|
||||
}
|
||||
if *res.CopySourceVersionId != srcObjVersionId {
|
||||
return fmt.Errorf("expected the SourceVersionId to be %v, instead got %v", srcObjVersionId, *res.CopySourceVersionId)
|
||||
}
|
||||
|
||||
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
|
||||
out, err := s3client.HeadObject(ctx, &s3.HeadObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &dstObj,
|
||||
VersionId: res.VersionId,
|
||||
})
|
||||
cancel()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if *out.VersionId != *res.VersionId {
|
||||
return fmt.Errorf("expected the copied object versionId to be %v, instead got %v", *res.VersionId, *out.VersionId)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, withVersioning())
|
||||
}
|
||||
|
||||
func Versioning_HeadObject_invalid_versionId(s *S3Conf) error {
|
||||
testName := "Versioning_HeadObject_invalid_versionId"
|
||||
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
|
||||
|
||||
Reference in New Issue
Block a user