mirror of
https://github.com/minio/minio.git
synced 2025-01-11 23:13:23 -05:00
handler: CopyObject should save metadata. (#1698)
- Content-Type - Content-Encoding - ETag Fixes #1682
This commit is contained in:
parent
00d0558131
commit
9fdb69563d
@ -492,7 +492,12 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
|
|||||||
writeErrorResponse(w, r, apiErr, r.URL.Path)
|
writeErrorResponse(w, r, apiErr, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
md5Sum, err := api.ObjectAPI.PutObject(bucket, object, -1, fileBody, nil)
|
|
||||||
|
// Save metadata.
|
||||||
|
metadata := make(map[string]string)
|
||||||
|
// Nothing to store right now.
|
||||||
|
|
||||||
|
md5Sum, err := api.ObjectAPI.PutObject(bucket, object, -1, fileBody, metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err, "Unable to create object.")
|
errorIf(err, "Unable to create object.")
|
||||||
writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
|
writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
|
||||||
|
@ -85,6 +85,10 @@ func newMultipartUploadCommon(storage StorageAPI, bucket string, object string,
|
|||||||
if !IsValidObjectName(object) {
|
if !IsValidObjectName(object) {
|
||||||
return "", ObjectNameInvalid{Bucket: bucket, Object: object}
|
return "", ObjectNameInvalid{Bucket: bucket, Object: object}
|
||||||
}
|
}
|
||||||
|
// No metadata is set, allocate a new one.
|
||||||
|
if meta == nil {
|
||||||
|
meta = make(map[string]string)
|
||||||
|
}
|
||||||
// This lock needs to be held for any changes to the directory contents of ".minio/multipart/object/"
|
// This lock needs to be held for any changes to the directory contents of ".minio/multipart/object/"
|
||||||
nsMutex.Lock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object))
|
nsMutex.Lock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object))
|
||||||
defer nsMutex.Unlock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object))
|
defer nsMutex.Unlock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object))
|
||||||
|
@ -28,13 +28,14 @@ type BucketInfo struct {
|
|||||||
|
|
||||||
// ObjectInfo - object info.
|
// ObjectInfo - object info.
|
||||||
type ObjectInfo struct {
|
type ObjectInfo struct {
|
||||||
Bucket string
|
Bucket string
|
||||||
Name string
|
Name string
|
||||||
ModTime time.Time
|
ModTime time.Time
|
||||||
ContentType string
|
Size int64
|
||||||
MD5Sum string
|
IsDir bool
|
||||||
Size int64
|
MD5Sum string
|
||||||
IsDir bool
|
ContentType string
|
||||||
|
ContentEncoding string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListPartsInfo - various types of object resources.
|
// ListPartsInfo - various types of object resources.
|
||||||
|
@ -404,8 +404,16 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
// Size of object.
|
// Size of object.
|
||||||
size := objInfo.Size
|
size := objInfo.Size
|
||||||
|
|
||||||
|
// Save metadata.
|
||||||
|
metadata := make(map[string]string)
|
||||||
|
// Save other metadata if available.
|
||||||
|
metadata["content-type"] = objInfo.ContentType
|
||||||
|
metadata["content-encoding"] = objInfo.ContentEncoding
|
||||||
|
// Do not set `md5sum` as CopyObject will not keep the
|
||||||
|
// same md5sum as the source.
|
||||||
|
|
||||||
// Create the object.
|
// Create the object.
|
||||||
md5Sum, err := api.ObjectAPI.PutObject(bucket, object, size, readCloser, nil)
|
md5Sum, err := api.ObjectAPI.PutObject(bucket, object, size, readCloser, metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err, "Unable to create an object.")
|
errorIf(err, "Unable to create an object.")
|
||||||
writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
|
writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
|
||||||
|
@ -624,6 +624,7 @@ func (s *MyAPIXLSuite) TestPutBucket(c *C) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests copy object.
|
||||||
func (s *MyAPIXLSuite) TestCopyObject(c *C) {
|
func (s *MyAPIXLSuite) TestCopyObject(c *C) {
|
||||||
request, err := s.newRequest("PUT", testAPIXLServer.URL+"/put-object-copy", 0, nil)
|
request, err := s.newRequest("PUT", testAPIXLServer.URL+"/put-object-copy", 0, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
@ -635,6 +636,7 @@ func (s *MyAPIXLSuite) TestCopyObject(c *C) {
|
|||||||
|
|
||||||
buffer1 := bytes.NewReader([]byte("hello world"))
|
buffer1 := bytes.NewReader([]byte("hello world"))
|
||||||
request, err = s.newRequest("PUT", testAPIXLServer.URL+"/put-object-copy/object", int64(buffer1.Len()), buffer1)
|
request, err = s.newRequest("PUT", testAPIXLServer.URL+"/put-object-copy/object", int64(buffer1.Len()), buffer1)
|
||||||
|
request.Header.Set("Content-Type", "application/json")
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
response, err = client.Do(request)
|
response, err = client.Do(request)
|
||||||
@ -657,8 +659,8 @@ func (s *MyAPIXLSuite) TestCopyObject(c *C) {
|
|||||||
c.Assert(response.StatusCode, Equals, http.StatusOK)
|
c.Assert(response.StatusCode, Equals, http.StatusOK)
|
||||||
object, err := ioutil.ReadAll(response.Body)
|
object, err := ioutil.ReadAll(response.Body)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
c.Assert(string(object), Equals, "hello world")
|
c.Assert(string(object), Equals, "hello world")
|
||||||
|
c.Assert(response.Header.Get("Content-Type"), Equals, "application/json")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MyAPIXLSuite) TestPutObject(c *C) {
|
func (s *MyAPIXLSuite) TestPutObject(c *C) {
|
||||||
|
@ -37,11 +37,12 @@ type MultipartPartInfo struct {
|
|||||||
// MultipartObjectInfo - contents of the multipart metadata file after
|
// MultipartObjectInfo - contents of the multipart metadata file after
|
||||||
// CompleteMultipartUpload() is called.
|
// CompleteMultipartUpload() is called.
|
||||||
type MultipartObjectInfo struct {
|
type MultipartObjectInfo struct {
|
||||||
Parts []MultipartPartInfo
|
Parts []MultipartPartInfo
|
||||||
ModTime time.Time
|
ModTime time.Time
|
||||||
Size int64
|
Size int64
|
||||||
MD5Sum string
|
MD5Sum string
|
||||||
ContentType string
|
ContentType string
|
||||||
|
ContentEncoding string
|
||||||
// Add more fields here.
|
// Add more fields here.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,6 +213,7 @@ func (xl xlObjects) CompleteMultipartUpload(bucket string, object string, upload
|
|||||||
// Save successfully calculated md5sum.
|
// Save successfully calculated md5sum.
|
||||||
metadata.MD5Sum = s3MD5
|
metadata.MD5Sum = s3MD5
|
||||||
metadata.ContentType = objMeta["content-type"]
|
metadata.ContentType = objMeta["content-type"]
|
||||||
|
metadata.ContentEncoding = objMeta["content-encoding"]
|
||||||
|
|
||||||
// Save modTime as well as the current time.
|
// Save modTime as well as the current time.
|
||||||
metadata.ModTime = time.Now().UTC()
|
metadata.ModTime = time.Now().UTC()
|
||||||
|
@ -250,6 +250,7 @@ func (xl xlObjects) getObjectInfo(bucket, object string) (objInfo ObjectInfo, er
|
|||||||
objInfo.ModTime = info.ModTime
|
objInfo.ModTime = info.ModTime
|
||||||
objInfo.MD5Sum = info.MD5Sum
|
objInfo.MD5Sum = info.MD5Sum
|
||||||
objInfo.ContentType = info.ContentType
|
objInfo.ContentType = info.ContentType
|
||||||
|
objInfo.ContentEncoding = info.ContentEncoding
|
||||||
} else {
|
} else {
|
||||||
metadata := make(map[string]string)
|
metadata := make(map[string]string)
|
||||||
offset := int64(0) // To read entire content
|
offset := int64(0) // To read entire content
|
||||||
@ -276,6 +277,7 @@ func (xl xlObjects) getObjectInfo(bucket, object string) (objInfo ObjectInfo, er
|
|||||||
objInfo.ModTime = fi.ModTime
|
objInfo.ModTime = fi.ModTime
|
||||||
objInfo.MD5Sum = metadata["md5Sum"]
|
objInfo.MD5Sum = metadata["md5Sum"]
|
||||||
objInfo.ContentType = contentType
|
objInfo.ContentType = contentType
|
||||||
|
objInfo.ContentEncoding = metadata["content-encoding"]
|
||||||
}
|
}
|
||||||
return objInfo, nil
|
return objInfo, nil
|
||||||
}
|
}
|
||||||
@ -315,6 +317,10 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
|
|||||||
Object: object,
|
Object: object,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// No metadata is set, allocate a new one.
|
||||||
|
if metadata == nil {
|
||||||
|
metadata = make(map[string]string)
|
||||||
|
}
|
||||||
nsMutex.Lock(bucket, object)
|
nsMutex.Lock(bucket, object)
|
||||||
defer nsMutex.Unlock(bucket, object)
|
defer nsMutex.Unlock(bucket, object)
|
||||||
|
|
||||||
@ -348,11 +354,13 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
|
|||||||
}
|
}
|
||||||
|
|
||||||
newMD5Hex := hex.EncodeToString(md5Writer.Sum(nil))
|
newMD5Hex := hex.EncodeToString(md5Writer.Sum(nil))
|
||||||
// md5Hex representation.
|
// Update the md5sum if not set with the newly calculated one.
|
||||||
var md5Hex string
|
if len(metadata["md5Sum"]) == 0 {
|
||||||
if len(metadata) != 0 {
|
metadata["md5Sum"] = newMD5Hex
|
||||||
md5Hex = metadata["md5Sum"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// md5Hex representation.
|
||||||
|
md5Hex := metadata["md5Sum"]
|
||||||
if md5Hex != "" {
|
if md5Hex != "" {
|
||||||
if newMD5Hex != md5Hex {
|
if newMD5Hex != md5Hex {
|
||||||
if err = safeCloseAndRemove(fileWriter); err != nil {
|
if err = safeCloseAndRemove(fileWriter); err != nil {
|
||||||
@ -361,6 +369,7 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
|
|||||||
return "", BadDigest{md5Hex, newMD5Hex}
|
return "", BadDigest{md5Hex, newMD5Hex}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = fileWriter.Close()
|
err = fileWriter.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if clErr := safeCloseAndRemove(fileWriter); clErr != nil {
|
if clErr := safeCloseAndRemove(fileWriter); clErr != nil {
|
||||||
@ -369,7 +378,7 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
|
|||||||
return "", toObjectErr(err, bucket, object)
|
return "", toObjectErr(err, bucket, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if an object is present as one of the parent dir.
|
// Check if an object is present as one of the parent dir.
|
||||||
if err = xl.parentDirIsObject(bucket, path.Dir(object)); err != nil {
|
if err = xl.parentDirIsObject(bucket, path.Dir(object)); err != nil {
|
||||||
return "", toObjectErr(err, bucket, object)
|
return "", toObjectErr(err, bucket, object)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user