@ -288,9 +288,6 @@ func (api objectAPIHandlers) HeadObjectHandler(w http.ResponseWriter, r *http.Re
// Extract metadata relevant for an CopyObject operation based on conditional
// Extract metadata relevant for an CopyObject operation based on conditional
// header values specified in X-Amz-Metadata-Directive.
// header values specified in X-Amz-Metadata-Directive.
func getCpObjMetadataFromHeader ( header http . Header , defaultMeta map [ string ] string ) ( map [ string ] string , error ) {
func getCpObjMetadataFromHeader ( header http . Header , defaultMeta map [ string ] string ) ( map [ string ] string , error ) {
// Make sure to remove saved etag if any, CopyObject calculates a new one.
delete ( defaultMeta , "etag" )
// if x-amz-metadata-directive says REPLACE then
// if x-amz-metadata-directive says REPLACE then
// we extract metadata from the input headers.
// we extract metadata from the input headers.
if isMetadataReplace ( header ) {
if isMetadataReplace ( header ) {
@ -357,30 +354,33 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
cpSrcDstSame := srcBucket == dstBucket && srcObject == dstObject
cpSrcDstSame := srcBucket == dstBucket && srcObject == dstObject
obj Info, err := objectAPI . GetObjectInfo ( srcBucket , srcObject )
src Info, err := objectAPI . GetObjectInfo ( srcBucket , srcObject )
if err != nil {
if err != nil {
writeErrorResponse ( w , toAPIErrorCode ( err ) , r . URL )
writeErrorResponse ( w , toAPIErrorCode ( err ) , r . URL )
return
return
}
}
// Verify before x-amz-copy-source preconditions before continuing with CopyObject.
// Verify before x-amz-copy-source preconditions before continuing with CopyObject.
if checkCopyObjectPreconditions ( w , r , obj Info) {
if checkCopyObjectPreconditions ( w , r , src Info) {
return
return
}
}
/// maximum Upload size for object in a single CopyObject operation.
/// maximum Upload size for object in a single CopyObject operation.
if isMaxObjectSize ( obj Info. Size ) {
if isMaxObjectSize ( src Info. Size ) {
writeErrorResponse ( w , ErrEntityTooLarge , r . URL )
writeErrorResponse ( w , ErrEntityTooLarge , r . URL )
return
return
}
}
newMetadata , err : = getCpObjMetadataFromHeader ( r . Header , obj Info. UserDefined )
srcInfo . UserDefined , err = getCpObjMetadataFromHeader ( r . Header , src Info. UserDefined )
if err != nil {
if err != nil {
errorIf ( err , "found invalid http request header" )
errorIf ( err , "found invalid http request header" )
writeErrorResponse ( w , ErrInternalError , r . URL )
writeErrorResponse ( w , ErrInternalError , r . URL )
return
return
}
}
// Make sure to remove saved etag if any, CopyObject calculates a new one.
delete ( srcInfo . UserDefined , "etag" )
// Check if x-amz-metadata-directive was not set to REPLACE and source,
// Check if x-amz-metadata-directive was not set to REPLACE and source,
// desination are same objects.
// desination are same objects.
if ! isMetadataReplace ( r . Header ) && cpSrcDstSame {
if ! isMetadataReplace ( r . Header ) && cpSrcDstSame {
@ -392,7 +392,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
// Copy source object to destination, if source and destination
// Copy source object to destination, if source and destination
// object is same then only metadata is updated.
// object is same then only metadata is updated.
objInfo , err = objectAPI . CopyObject ( srcBucket , srcObject , dstBucket , dstObject , newMetadata , objInfo . ETag )
objInfo , err : = objectAPI . CopyObject ( srcBucket , srcObject , dstBucket , dstObject , srcInfo )
if err != nil {
if err != nil {
writeErrorResponse ( w , toAPIErrorCode ( err ) , r . URL )
writeErrorResponse ( w , toAPIErrorCode ( err ) , r . URL )
return
return
@ -713,7 +713,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
return
return
}
}
obj Info, err := objectAPI . GetObjectInfo ( srcBucket , srcObject )
src Info, err := objectAPI . GetObjectInfo ( srcBucket , srcObject )
if err != nil {
if err != nil {
writeErrorResponse ( w , toAPIErrorCode ( err ) , r . URL )
writeErrorResponse ( w , toAPIErrorCode ( err ) , r . URL )
return
return
@ -723,7 +723,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
var hrange * httpRange
var hrange * httpRange
rangeHeader := r . Header . Get ( "x-amz-copy-source-range" )
rangeHeader := r . Header . Get ( "x-amz-copy-source-range" )
if rangeHeader != "" {
if rangeHeader != "" {
if hrange , err = parseCopyPartRange ( rangeHeader , obj Info. Size ) ; err != nil {
if hrange , err = parseCopyPartRange ( rangeHeader , src Info. Size ) ; err != nil {
// Handle only errInvalidRange
// Handle only errInvalidRange
// Ignore other parse error and treat it as regular Get request like Amazon S3.
// Ignore other parse error and treat it as regular Get request like Amazon S3.
errorIf ( err , "Unable to extract range %s" , rangeHeader )
errorIf ( err , "Unable to extract range %s" , rangeHeader )
@ -733,13 +733,13 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
}
}
// Verify before x-amz-copy-source preconditions before continuing with CopyObject.
// Verify before x-amz-copy-source preconditions before continuing with CopyObject.
if checkCopyObjectPartPreconditions ( w , r , obj Info) {
if checkCopyObjectPartPreconditions ( w , r , src Info) {
return
return
}
}
// Get the object.
// Get the object.
var startOffset int64
var startOffset int64
length := obj Info. Size
length := src Info. Size
if hrange != nil {
if hrange != nil {
length = hrange . getLength ( )
length = hrange . getLength ( )
startOffset = hrange . offsetBegin
startOffset = hrange . offsetBegin
@ -751,10 +751,13 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
return
return
}
}
// Make sure to remove all metadata from source for for multipart operations.
srcInfo . UserDefined = nil
// Copy source object to destination, if source and destination
// Copy source object to destination, if source and destination
// object is same then only metadata is updated.
// object is same then only metadata is updated.
partInfo , err := objectAPI . CopyObjectPart ( srcBucket , srcObject , dstBucket ,
partInfo , err := objectAPI . CopyObjectPart ( srcBucket , srcObject , dstBucket ,
dstObject , uploadID , partID , startOffset , length , nil , objInfo . ETag )
dstObject , uploadID , partID , startOffset , length , srcInfo )
if err != nil {
if err != nil {
writeErrorResponse ( w , toAPIErrorCode ( err ) , r . URL )
writeErrorResponse ( w , toAPIErrorCode ( err ) , r . URL )
return
return