|
|
@ -24,7 +24,6 @@ import ( |
|
|
|
"encoding/hex" |
|
|
|
"encoding/hex" |
|
|
|
"encoding/xml" |
|
|
|
"encoding/xml" |
|
|
|
"io" |
|
|
|
"io" |
|
|
|
goioutil "io/ioutil" |
|
|
|
|
|
|
|
"net/http" |
|
|
|
"net/http" |
|
|
|
"net/url" |
|
|
|
"net/url" |
|
|
|
"sort" |
|
|
|
"sort" |
|
|
@ -2331,12 +2330,19 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Content-Length is required and should be non-zero
|
|
|
|
|
|
|
|
if r.ContentLength <= 0 { |
|
|
|
|
|
|
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrMissingContentLength), r.URL, guessIsBrowserReq(r)) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Reject retention or governance headers if set, CompleteMultipartUpload spec
|
|
|
|
// Reject retention or governance headers if set, CompleteMultipartUpload spec
|
|
|
|
// does not use these headers, and should not be passed down to checkPutObjectLockAllowed
|
|
|
|
// does not use these headers, and should not be passed down to checkPutObjectLockAllowed
|
|
|
|
if objectlock.IsObjectLockRequested(r.Header) || objectlock.IsObjectLockGovernanceBypassSet(r.Header) { |
|
|
|
if objectlock.IsObjectLockRequested(r.Header) || objectlock.IsObjectLockGovernanceBypassSet(r.Header) { |
|
|
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL, guessIsBrowserReq(r)) |
|
|
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL, guessIsBrowserReq(r)) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Enforce object lock governance in case a competing upload finalized first.
|
|
|
|
// Enforce object lock governance in case a competing upload finalized first.
|
|
|
|
retPerms := isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectRetentionAction) |
|
|
|
retPerms := isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectRetentionAction) |
|
|
|
holdPerms := isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectLegalHoldAction) |
|
|
|
holdPerms := isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectLegalHoldAction) |
|
|
@ -2353,14 +2359,9 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
completeMultipartBytes, err := goioutil.ReadAll(r.Body) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
complMultipartUpload := &CompleteMultipartUpload{} |
|
|
|
complMultipartUpload := &CompleteMultipartUpload{} |
|
|
|
if err = xml.Unmarshal(completeMultipartBytes, complMultipartUpload); err != nil { |
|
|
|
if err = xmlDecoder(r.Body, complMultipartUpload, r.ContentLength); err != nil { |
|
|
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrMalformedXML), r.URL, guessIsBrowserReq(r)) |
|
|
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
if len(complMultipartUpload.Parts) == 0 { |
|
|
|
if len(complMultipartUpload.Parts) == 0 { |
|
|
|