Generate random ETag if client does not provide MD5 for PutObjectPart (#4385)

fixes #4289
fixes #4290
This commit is contained in:
Krishna Srinivas 2017-05-22 15:42:00 -07:00 committed by Harshavardhana
parent 9136734c02
commit 28c26a9e59
2 changed files with 63 additions and 7 deletions

View File

@ -17,6 +17,7 @@
package cmd package cmd
import ( import (
"crypto/md5"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
@ -313,24 +314,47 @@ func canonicalMetadata(metadata map[string]string) (canonical map[string]string)
// uses Azure equivalent CreateBlockBlobFromReader. // uses Azure equivalent CreateBlockBlobFromReader.
func (a *azureObjects) PutObject(bucket, object string, size int64, data io.Reader, metadata map[string]string, sha256sum string) (objInfo ObjectInfo, err error) { func (a *azureObjects) PutObject(bucket, object string, size int64, data io.Reader, metadata map[string]string, sha256sum string) (objInfo ObjectInfo, err error) {
var sha256Writer hash.Hash var sha256Writer hash.Hash
var md5sumWriter hash.Hash
var writers []io.Writer
md5sum := metadata["etag"]
delete(metadata, "etag")
teeReader := data teeReader := data
if sha256sum != "" { if sha256sum != "" {
sha256Writer = sha256.New() sha256Writer = sha256.New()
teeReader = io.TeeReader(data, sha256Writer) writers = append(writers, sha256Writer)
} }
delete(metadata, "etag") if md5sum != "" {
md5sumWriter = md5.New()
writers = append(writers, md5sumWriter)
}
if len(writers) > 0 {
teeReader = io.TeeReader(data, io.MultiWriter(writers...))
}
err = a.client.CreateBlockBlobFromReader(bucket, object, uint64(size), teeReader, canonicalMetadata(metadata)) err = a.client.CreateBlockBlobFromReader(bucket, object, uint64(size), teeReader, canonicalMetadata(metadata))
if err != nil { if err != nil {
return objInfo, azureToObjectError(traceError(err), bucket, object) return objInfo, azureToObjectError(traceError(err), bucket, object)
} }
if md5sum != "" {
newMD5sum := hex.EncodeToString(md5sumWriter.Sum(nil))
if newMD5sum != md5sum {
a.client.DeleteBlob(bucket, object, nil)
return ObjectInfo{}, azureToObjectError(traceError(BadDigest{md5sum, newMD5sum}))
}
}
if sha256sum != "" { if sha256sum != "" {
newSHA256sum := hex.EncodeToString(sha256Writer.Sum(nil)) newSHA256sum := hex.EncodeToString(sha256Writer.Sum(nil))
if newSHA256sum != sha256sum { if newSHA256sum != sha256sum {
a.client.DeleteBlob(bucket, object, nil) a.client.DeleteBlob(bucket, object, nil)
return ObjectInfo{}, traceError(SHA256Mismatch{}) return ObjectInfo{}, azureToObjectError(traceError(SHA256Mismatch{}))
} }
} }
@ -426,27 +450,54 @@ func (a *azureObjects) PutObjectPart(bucket, object, uploadID string, partID int
return info, traceError(InvalidUploadID{}) return info, traceError(InvalidUploadID{})
} }
var sha256Writer hash.Hash var sha256Writer hash.Hash
var md5sumWriter hash.Hash
var etag string
var writers []io.Writer
if sha256sum != "" { if sha256sum != "" {
sha256Writer = sha256.New() sha256Writer = sha256.New()
writers = append(writers, sha256Writer)
} }
teeReader := io.TeeReader(data, sha256Writer) if md5Hex != "" {
md5sumWriter = md5.New()
writers = append(writers, md5sumWriter)
etag = md5Hex
} else {
// Generate random ETag.
etag = getMD5Hash([]byte(mustGetUUID()))
}
id := azureGetBlockID(partID, md5Hex) teeReader := data
if len(writers) > 0 {
teeReader = io.TeeReader(data, io.MultiWriter(writers...))
}
id := azureGetBlockID(partID, etag)
err = a.client.PutBlockWithLength(bucket, object, id, uint64(size), teeReader, nil) err = a.client.PutBlockWithLength(bucket, object, id, uint64(size), teeReader, nil)
if err != nil { if err != nil {
return info, azureToObjectError(traceError(err), bucket, object) return info, azureToObjectError(traceError(err), bucket, object)
} }
if md5Hex != "" {
newMD5sum := hex.EncodeToString(md5sumWriter.Sum(nil))
if newMD5sum != md5Hex {
a.client.DeleteBlob(bucket, object, nil)
return PartInfo{}, azureToObjectError(traceError(BadDigest{md5Hex, newMD5sum}))
}
}
if sha256sum != "" { if sha256sum != "" {
newSHA256sum := hex.EncodeToString(sha256Writer.Sum(nil)) newSHA256sum := hex.EncodeToString(sha256Writer.Sum(nil))
if newSHA256sum != sha256sum { if newSHA256sum != sha256sum {
return PartInfo{}, traceError(SHA256Mismatch{}) return PartInfo{}, azureToObjectError(traceError(SHA256Mismatch{}))
} }
} }
info.PartNumber = partID info.PartNumber = partID
info.ETag = md5Hex info.ETag = etag
info.LastModified = UTCNow() info.LastModified = UTCNow()
info.Size = size info.Size = size
return info, nil return info, nil

View File

@ -282,6 +282,11 @@ func (api gatewayAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Re
return return
} }
if err != nil {
writeErrorResponse(w, toAPIErrorCode(err), r.URL)
return
}
w.Header().Set("ETag", "\""+objInfo.ETag+"\"") w.Header().Set("ETag", "\""+objInfo.ETag+"\"")
writeSuccessResponseHeadersOnly(w) writeSuccessResponseHeadersOnly(w)
} }