handler: CopyObject should save metadata. (#1698)

- Content-Type
- Content-Encoding
- ETag

Fixes #1682
This commit is contained in:
Harshavardhana 2016-05-19 17:10:08 -07:00 committed by Anand Babu (AB) Periasamy
parent 00d0558131
commit 9fdb69563d
7 changed files with 51 additions and 20 deletions

View File

@ -492,7 +492,12 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
writeErrorResponse(w, r, apiErr, r.URL.Path)
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 {
errorIf(err, "Unable to create object.")
writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)

View File

@ -85,6 +85,10 @@ func newMultipartUploadCommon(storage StorageAPI, bucket string, object string,
if !IsValidObjectName(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/"
nsMutex.Lock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object))
defer nsMutex.Unlock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object))

View File

@ -28,13 +28,14 @@ type BucketInfo struct {
// ObjectInfo - object info.
type ObjectInfo struct {
Bucket string
Name string
ModTime time.Time
ContentType string
MD5Sum string
Size int64
IsDir bool
Bucket string
Name string
ModTime time.Time
Size int64
IsDir bool
MD5Sum string
ContentType string
ContentEncoding string
}
// ListPartsInfo - various types of object resources.

View File

@ -404,8 +404,16 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
// Size of object.
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.
md5Sum, err := api.ObjectAPI.PutObject(bucket, object, size, readCloser, nil)
md5Sum, err := api.ObjectAPI.PutObject(bucket, object, size, readCloser, metadata)
if err != nil {
errorIf(err, "Unable to create an object.")
writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)

View File

@ -624,6 +624,7 @@ func (s *MyAPIXLSuite) TestPutBucket(c *C) {
}
// Tests copy object.
func (s *MyAPIXLSuite) TestCopyObject(c *C) {
request, err := s.newRequest("PUT", testAPIXLServer.URL+"/put-object-copy", 0, nil)
c.Assert(err, IsNil)
@ -635,6 +636,7 @@ func (s *MyAPIXLSuite) TestCopyObject(c *C) {
buffer1 := bytes.NewReader([]byte("hello world"))
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)
response, err = client.Do(request)
@ -657,8 +659,8 @@ func (s *MyAPIXLSuite) TestCopyObject(c *C) {
c.Assert(response.StatusCode, Equals, http.StatusOK)
object, err := ioutil.ReadAll(response.Body)
c.Assert(err, IsNil)
c.Assert(string(object), Equals, "hello world")
c.Assert(response.Header.Get("Content-Type"), Equals, "application/json")
}
func (s *MyAPIXLSuite) TestPutObject(c *C) {

View File

@ -37,11 +37,12 @@ type MultipartPartInfo struct {
// MultipartObjectInfo - contents of the multipart metadata file after
// CompleteMultipartUpload() is called.
type MultipartObjectInfo struct {
Parts []MultipartPartInfo
ModTime time.Time
Size int64
MD5Sum string
ContentType string
Parts []MultipartPartInfo
ModTime time.Time
Size int64
MD5Sum string
ContentType string
ContentEncoding string
// Add more fields here.
}
@ -212,6 +213,7 @@ func (xl xlObjects) CompleteMultipartUpload(bucket string, object string, upload
// Save successfully calculated md5sum.
metadata.MD5Sum = s3MD5
metadata.ContentType = objMeta["content-type"]
metadata.ContentEncoding = objMeta["content-encoding"]
// Save modTime as well as the current time.
metadata.ModTime = time.Now().UTC()

View File

@ -250,6 +250,7 @@ func (xl xlObjects) getObjectInfo(bucket, object string) (objInfo ObjectInfo, er
objInfo.ModTime = info.ModTime
objInfo.MD5Sum = info.MD5Sum
objInfo.ContentType = info.ContentType
objInfo.ContentEncoding = info.ContentEncoding
} else {
metadata := make(map[string]string)
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.MD5Sum = metadata["md5Sum"]
objInfo.ContentType = contentType
objInfo.ContentEncoding = metadata["content-encoding"]
}
return objInfo, nil
}
@ -315,6 +317,10 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
Object: object,
}
}
// No metadata is set, allocate a new one.
if metadata == nil {
metadata = make(map[string]string)
}
nsMutex.Lock(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))
// md5Hex representation.
var md5Hex string
if len(metadata) != 0 {
md5Hex = metadata["md5Sum"]
// Update the md5sum if not set with the newly calculated one.
if len(metadata["md5Sum"]) == 0 {
metadata["md5Sum"] = newMD5Hex
}
// md5Hex representation.
md5Hex := metadata["md5Sum"]
if md5Hex != "" {
if newMD5Hex != md5Hex {
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}
}
}
err = fileWriter.Close()
if err != 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)
}
// 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 {
return "", toObjectErr(err, bucket, object)
}