-
Notifications
You must be signed in to change notification settings - Fork 647
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new CopyObject API in Core client #836
Conversation
core.go
Outdated
return c.putObjectDo(context.Background(), bucket, object, data, md5Sum, sha256Sum, size, PutObjectOptions{UserMetadata: metadata}) | ||
delKey := func(m map[string]string, key string) { | ||
delete(m, strings.ToLower(key)) | ||
delete(m, strings.ToUpper(key)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will miss key in mixed-case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you give me an example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
example - if "Content-Type" is a key in the metadata map, the above code will not delete the entry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops yeah i should have used http.CanonicalHeaderKey()
core.go
Outdated
if v := getKeyValue(metadata, "content-encoding"); v != "" { | ||
opts.ContentEncoding = v | ||
delKey(metadata, "content-encoding") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
opts := PutObjectOptions{}
m := make(map[string]string)
for k, v := range metadata {
if strings.ToLower(k) == "content-encoding" {
opts.ContentEncoding = v
} else if strings.ToLower(k) == "content-disposition" {
opts.ContentDisposition = v
} else if strings.ToLower(k) == "content-type" {
opts.ContentType = v
} else if strings.ToLower(k) == "cache-control" {
opts.CacheControl = v
} else {
m[k] = metadata[k]
}
}
opts.UserMetadata = m
this would be more concise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense..
// CopyObject - copies an object from source object to destination object on server side. | ||
func (c Core) CopyObject(sourceBucket, sourceObject, destBucket, destObject string, metadata map[string]string) (ObjectInfo, error) { | ||
return c.copyObjectDo(context.Background(), sourceBucket, sourceObject, destBucket, destObject, metadata) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
7b6a531
to
e819428
Compare
This PR also fixes the problem of PutObject call not handling additional headers. Refer original problem here minio/minio#5000
e819428
to
9af77c8
Compare
Sorry to come in late on this. The bug identified minio/minio#5000 (comment) can be fixed properly in ComposeObject(). Particularly, this part https://github.com/minio/minio-go/blob/master/api-compose-object.go#L110-L122 needs to be fixed to handle the standard headers (like Content-Encoding, etc). IIUC, then this PR is not needed (except perhaps to fix PutObject)? |
No we need to add a simpler version @donatello - we shouldn't use ComposeObject IMHO. Which uses multipart API underneath. |
@harshavardhana Got it, you're right. ComposeObject would also do a HEAD, which is not desirable in gateway mode where we do expect it to be a one-to-one API mapping. |
@@ -128,7 +128,7 @@ type initiator struct { | |||
// copyObjectResult container for copy object response. | |||
type copyObjectResult struct { | |||
ETag string | |||
LastModified string // time string format "2006-01-02T15:04:05.000Z" | |||
LastModified time.Time // time string format "2006-01-02T15:04:05.000Z" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would xmlDecoder()
know the format (time layout) with which to parse the time? I am not sure the decoding will be correct as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is the feature of xml Marshal @donatello also we need to have typed value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example look at all the List() APIs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@harshavardhana - xml decoder is using a particular format within the ISO8601 standard by default to parse timestamps. Looks like by dumb luck AWS is using the same format!
opts.ContentType = v | ||
} else if strings.ToLower(k) == "cache-control" { | ||
opts.CacheControl = v | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two headers seem to be missing from this list - content-length
and content-md5
according to https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is set internally @donatello
// Set all the metadata headers. | ||
for k, v := range metadata { | ||
headers.Set(k, v) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For metadata replacement to actually happen we need to make sure the x-amz-metadata-directive
header is set to REPLACE
. Perhaps we should throw an error if metadata
is non-empty and this header is not set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right let me do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually we don't need to.. there is no error @donatello according to CopyObject() if REPLACE is set then the set metadata is honored, otherwise it does copy from the source object by default. So we don't need to error out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes. It is not needed, as AWS behaviour is also to silently ignore the headers without the directive header.
This PR also fixes the problem of PutObject
call not handling additional headers.
Refer original problem here minio/minio#5000