handlers: overhaul entire writErrorResponse, simplify. (#1472)

This commit is contained in:
Harshavardhana 2016-05-05 20:24:29 -07:00 committed by Anand Babu (AB) Periasamy
parent ba5805e60a
commit 17868ccd7f
7 changed files with 120 additions and 317 deletions

View File

@ -108,8 +108,8 @@ const (
// Add new error codes here. // Add new error codes here.
// Extended errors. // Extended errors.
ErrInsufficientReadResources ErrReadQuorum
ErrInsufficientWriteResources ErrWriteQuorum
) )
// error code to APIError structure, these fields carry respective // error code to APIError structure, these fields carry respective
@ -190,15 +190,15 @@ var errorCodeResponse = map[APIErrorCode]APIError{
Description: "We encountered an internal error, please try again.", Description: "We encountered an internal error, please try again.",
HTTPStatusCode: http.StatusInternalServerError, HTTPStatusCode: http.StatusInternalServerError,
}, },
ErrInsufficientReadResources: { ErrReadQuorum: {
Code: "InternalError", Code: "ReadQuorum",
Description: "We cannot satisfy sufficient read resources requested at this moment, please try again.", Description: "Multiple disk failures, unable to reconstruct data.",
HTTPStatusCode: http.StatusInternalServerError, HTTPStatusCode: http.StatusServiceUnavailable,
}, },
ErrInsufficientWriteResources: { ErrWriteQuorum: {
Code: "InternalError", Code: "WriteQuorum",
Description: "We cannot satisfy sufficient write resources requested at this moment, please try again.", Description: "Multiple disks failures, unable to write data.",
HTTPStatusCode: http.StatusInternalServerError, HTTPStatusCode: http.StatusServiceUnavailable,
}, },
ErrInvalidAccessKeyID: { ErrInvalidAccessKeyID: {
Code: "InvalidAccessKeyID", Code: "InvalidAccessKeyID",
@ -418,6 +418,52 @@ var errorCodeResponse = map[APIErrorCode]APIError{
// Add your error structure here. // Add your error structure here.
} }
// toAPIErrorCode - Converts embedded errors. Convenience
// function written to handle all cases where we have known types of
// errors returned by underlying layers.
func toAPIErrorCode(err error) (apiErr APIErrorCode) {
if err == nil {
return ErrNone
}
// Verify if the underlying error is signature mismatch.
if err == errSignatureMismatch {
return ErrSignatureDoesNotMatch
}
switch err.(type) {
case StorageFull:
apiErr = ErrStorageFull
case BadDigest:
apiErr = ErrBadDigest
case IncompleteBody:
apiErr = ErrIncompleteBody
case ObjectExistsAsPrefix:
apiErr = ErrObjectExistsAsPrefix
case BucketNameInvalid:
apiErr = ErrInvalidBucketName
case BucketNotFound:
apiErr = ErrNoSuchBucket
case BucketNotEmpty:
apiErr = ErrBucketNotEmpty
case BucketExists:
apiErr = ErrBucketAlreadyOwnedByYou
case ObjectNotFound:
apiErr = ErrNoSuchKey
case ObjectNameInvalid:
apiErr = ErrNoSuchKey
case InvalidUploadID:
apiErr = ErrNoSuchUpload
case InvalidPart:
apiErr = ErrInvalidPart
case InsufficientWriteQuorum:
apiErr = ErrWriteQuorum
case InsufficientReadQuorum:
apiErr = ErrReadQuorum
default:
apiErr = ErrInternalError
}
return apiErr
}
// getAPIError provides API Error for input API error code. // getAPIError provides API Error for input API error code.
func getAPIError(code APIErrorCode) APIError { func getAPIError(code APIErrorCode) APIError {
return errorCodeResponse[code] return errorCodeResponse[code]

View File

@ -118,14 +118,7 @@ func (api objectAPIHandlers) GetBucketLocationHandler(w http.ResponseWriter, r *
if _, err := api.ObjectAPI.GetBucketInfo(bucket); err != nil { if _, err := api.ObjectAPI.GetBucketInfo(bucket); err != nil {
errorIf(err, "GetBucketInfo failed.", nil) errorIf(err, "GetBucketInfo failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
@ -196,12 +189,7 @@ func (api objectAPIHandlers) ListMultipartUploadsHandler(w http.ResponseWriter,
listMultipartsInfo, err := api.ObjectAPI.ListMultipartUploads(bucket, prefix, keyMarker, uploadIDMarker, delimiter, maxUploads) listMultipartsInfo, err := api.ObjectAPI.ListMultipartUploads(bucket, prefix, keyMarker, uploadIDMarker, delimiter, maxUploads)
if err != nil { if err != nil {
errorIf(err, "ListMultipartUploads failed.", nil) errorIf(err, "ListMultipartUploads failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
// generate response // generate response
@ -281,16 +269,7 @@ func (api objectAPIHandlers) ListObjectsHandler(w http.ResponseWriter, r *http.R
return return
} }
errorIf(err, "ListObjects failed.", nil) errorIf(err, "ListObjects failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case ObjectNameInvalid:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
} }
// ListBucketsHandler - GET Service // ListBucketsHandler - GET Service
@ -344,13 +323,7 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R
return return
} }
errorIf(err, "ListBuckets failed.", nil) errorIf(err, "ListBuckets failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case StorageInsufficientReadResources:
writeErrorResponse(w, r, ErrInsufficientReadResources, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
} }
// DeleteMultipleObjectsHandler - deletes multiple objects. // DeleteMultipleObjectsHandler - deletes multiple objects.
@ -419,38 +392,11 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
}) })
} else { } else {
errorIf(err, "DeleteObject failed.", nil) errorIf(err, "DeleteObject failed.", nil)
switch err.(type) { deleteErrors = append(deleteErrors, DeleteError{
case BucketNameInvalid: Code: errorCodeResponse[toAPIErrorCode(err)].Code,
deleteErrors = append(deleteErrors, DeleteError{ Message: errorCodeResponse[toAPIErrorCode(err)].Description,
Code: errorCodeResponse[ErrInvalidBucketName].Code, Key: object.ObjectName,
Message: errorCodeResponse[ErrInvalidBucketName].Description, })
Key: object.ObjectName,
})
case BucketNotFound:
deleteErrors = append(deleteErrors, DeleteError{
Code: errorCodeResponse[ErrNoSuchBucket].Code,
Message: errorCodeResponse[ErrNoSuchBucket].Description,
Key: object.ObjectName,
})
case ObjectNotFound:
deleteErrors = append(deleteErrors, DeleteError{
Code: errorCodeResponse[ErrNoSuchKey].Code,
Message: errorCodeResponse[ErrNoSuchKey].Description,
Key: object.ObjectName,
})
case ObjectNameInvalid:
deleteErrors = append(deleteErrors, DeleteError{
Code: errorCodeResponse[ErrNoSuchKey].Code,
Message: errorCodeResponse[ErrNoSuchKey].Description,
Key: object.ObjectName,
})
default:
deleteErrors = append(deleteErrors, DeleteError{
Code: errorCodeResponse[ErrInternalError].Code,
Message: errorCodeResponse[ErrInternalError].Description,
Key: object.ObjectName,
})
}
} }
} }
// Generate response // Generate response
@ -466,7 +412,6 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
// ---------- // ----------
// This implementation of the PUT operation creates a new bucket for authenticated request // This implementation of the PUT operation creates a new bucket for authenticated request
func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Request) { func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
bucket := vars["bucket"] bucket := vars["bucket"]
@ -495,14 +440,7 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req
err := api.ObjectAPI.MakeBucket(bucket) err := api.ObjectAPI.MakeBucket(bucket)
if err != nil { if err != nil {
errorIf(err, "MakeBucket failed.", nil) errorIf(err, "MakeBucket failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case BucketExists:
writeErrorResponse(w, r, ErrBucketAlreadyOwnedByYou, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
// Make sure to add Location information here only for bucket // Make sure to add Location information here only for bucket
@ -573,20 +511,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
md5Sum, err := api.ObjectAPI.PutObject(bucket, object, -1, fileBody, nil) md5Sum, err := api.ObjectAPI.PutObject(bucket, object, -1, fileBody, nil)
if err != nil { if err != nil {
errorIf(err, "PutObject failed.", nil) errorIf(err, "PutObject failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case StorageFull:
writeErrorResponse(w, r, ErrStorageFull, r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case BadDigest:
writeErrorResponse(w, r, ErrBadDigest, r.URL.Path)
case IncompleteBody:
writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
if md5Sum != "" { if md5Sum != "" {
@ -632,16 +557,7 @@ func (api objectAPIHandlers) HeadBucketHandler(w http.ResponseWriter, r *http.Re
if _, err := api.ObjectAPI.GetBucketInfo(bucket); err != nil { if _, err := api.ObjectAPI.GetBucketInfo(bucket); err != nil {
errorIf(err, "GetBucketInfo failed.", nil) errorIf(err, "GetBucketInfo failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case StorageInsufficientReadResources:
writeErrorResponse(w, r, ErrInsufficientReadResources, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
writeSuccessResponse(w, nil) writeSuccessResponse(w, nil)
@ -666,14 +582,7 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http.
if err := api.ObjectAPI.DeleteBucket(bucket); err != nil { if err := api.ObjectAPI.DeleteBucket(bucket); err != nil {
errorIf(err, "DeleteBucket failed.", nil) errorIf(err, "DeleteBucket failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case BucketNotEmpty:
writeErrorResponse(w, r, ErrBucketNotEmpty, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }

View File

@ -41,9 +41,9 @@ func toObjectErr(err error, params ...string) error {
case errDiskFull: case errDiskFull:
return StorageFull{} return StorageFull{}
case errReadQuorum: case errReadQuorum:
return StorageInsufficientReadResources{} return InsufficientReadQuorum{}
case errWriteQuorum: case errWriteQuorum:
return StorageInsufficientWriteResources{} return InsufficientWriteQuorum{}
case errIsNotRegular, errFileAccessDenied: case errIsNotRegular, errFileAccessDenied:
if len(params) >= 2 { if len(params) >= 2 {
return ObjectExistsAsPrefix{ return ObjectExistsAsPrefix{
@ -71,18 +71,18 @@ func (e StorageFull) Error() string {
return "Storage reached its minimum free disk threshold." return "Storage reached its minimum free disk threshold."
} }
// StorageInsufficientReadResources storage cannot satisfy quorum for read operation. // InsufficientReadQuorum storage cannot satisfy quorum for read operation.
type StorageInsufficientReadResources struct{} type InsufficientReadQuorum struct{}
func (e StorageInsufficientReadResources) Error() string { func (e InsufficientReadQuorum) Error() string {
return "Storage resources are insufficient for the read operation." return "Storage resources are insufficient for the read operation."
} }
// StorageInsufficientWriteResources storage cannot satisfy quorum for write operation. // InsufficientWriteQuorum storage cannot satisfy quorum for write operation.
type StorageInsufficientWriteResources struct{} type InsufficientWriteQuorum struct{}
func (e StorageInsufficientWriteResources) Error() string { func (e InsufficientWriteQuorum) Error() string {
return "Stroage resources are insufficient for the write operation." return "Storage resources are insufficient for the write operation."
} }
// GenericError - generic object layer error. // GenericError - generic object layer error.

View File

@ -65,7 +65,6 @@ func errAllowableObjectNotFound(bucket string, r *http.Request) APIErrorCode {
return ErrAccessDenied return ErrAccessDenied
} }
} }
return ErrNoSuchKey return ErrNoSuchKey
} }
@ -100,18 +99,11 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req
objInfo, err := api.ObjectAPI.GetObjectInfo(bucket, object) objInfo, err := api.ObjectAPI.GetObjectInfo(bucket, object)
if err != nil { if err != nil {
errorIf(err, "GetObjectInfo failed.", nil) errorIf(err, "GetObjectInfo failed.", nil)
switch err.(type) { apiErr := toAPIErrorCode(err)
case BucketNameInvalid: if apiErr == ErrNoSuchKey {
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) apiErr = errAllowableObjectNotFound(bucket, r)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case ObjectNotFound:
writeErrorResponse(w, r, errAllowableObjectNotFound(bucket, r), r.URL.Path)
case ObjectNameInvalid:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
} }
writeErrorResponse(w, r, apiErr, r.URL.Path)
return return
} }
@ -136,15 +128,12 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req
startOffset := hrange.start startOffset := hrange.start
readCloser, err := api.ObjectAPI.GetObject(bucket, object, startOffset) readCloser, err := api.ObjectAPI.GetObject(bucket, object, startOffset)
if err != nil { if err != nil {
switch err.(type) { errorIf(err, "GetObject failed.", nil)
case BucketNotFound: apiErr := toAPIErrorCode(err)
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path) if apiErr == ErrNoSuchKey {
case ObjectNotFound: apiErr = errAllowableObjectNotFound(bucket, r)
writeErrorResponse(w, r, errAllowableObjectNotFound(bucket, r), r.URL.Path)
default:
errorIf(err, "GetObject failed.", nil)
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
} }
writeErrorResponse(w, r, apiErr, r.URL.Path)
return return
} }
defer readCloser.Close() // Close after this handler returns. defer readCloser.Close() // Close after this handler returns.
@ -294,18 +283,11 @@ func (api objectAPIHandlers) HeadObjectHandler(w http.ResponseWriter, r *http.Re
objInfo, err := api.ObjectAPI.GetObjectInfo(bucket, object) objInfo, err := api.ObjectAPI.GetObjectInfo(bucket, object)
if err != nil { if err != nil {
errorIf(err, "GetObjectInfo failed.", nil) errorIf(err, "GetObjectInfo failed.", nil)
switch err.(type) { apiErr := toAPIErrorCode(err)
case BucketNameInvalid: if apiErr == ErrNoSuchKey {
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path) apiErr = errAllowableObjectNotFound(bucket, r)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case ObjectNotFound:
writeErrorResponse(w, r, errAllowableObjectNotFound(bucket, r), r.URL.Path)
case ObjectNameInvalid:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
} }
writeErrorResponse(w, r, apiErr, r.URL.Path)
return return
} }
@ -387,18 +369,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
objInfo, err := api.ObjectAPI.GetObjectInfo(sourceBucket, sourceObject) objInfo, err := api.ObjectAPI.GetObjectInfo(sourceBucket, sourceObject)
if err != nil { if err != nil {
errorIf(err, "GetObjectInfo failed.", nil) errorIf(err, "GetObjectInfo failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), objectSource)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, objectSource)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, objectSource)
case ObjectNotFound:
writeErrorResponse(w, r, ErrNoSuchKey, objectSource)
case ObjectNameInvalid:
writeErrorResponse(w, r, ErrNoSuchKey, objectSource)
default:
writeErrorResponse(w, r, ErrInternalError, objectSource)
}
return return
} }
// Verify before writing. // Verify before writing.
@ -437,14 +408,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
readCloser, err := api.ObjectAPI.GetObject(sourceBucket, sourceObject, startOffset) readCloser, err := api.ObjectAPI.GetObject(sourceBucket, sourceObject, startOffset)
if err != nil { if err != nil {
errorIf(err, "Reading "+objectSource+" failed.", nil) errorIf(err, "Reading "+objectSource+" failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), objectSource)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, objectSource)
case ObjectNotFound:
writeErrorResponse(w, r, ErrNoSuchKey, objectSource)
default:
writeErrorResponse(w, r, ErrInternalError, objectSource)
}
return return
} }
// Size of object. // Size of object.
@ -458,29 +422,14 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
md5Sum, err := api.ObjectAPI.PutObject(bucket, object, size, readCloser, metadata) md5Sum, err := api.ObjectAPI.PutObject(bucket, object, size, readCloser, metadata)
if err != nil { if err != nil {
errorIf(err, "PutObject failed.", nil) errorIf(err, "PutObject failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case StorageFull:
writeErrorResponse(w, r, ErrStorageFull, r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case BadDigest:
writeErrorResponse(w, r, ErrBadDigest, r.URL.Path)
case IncompleteBody:
writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path)
case ObjectExistsAsPrefix:
writeErrorResponse(w, r, ErrObjectExistsAsPrefix, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
objInfo, err = api.ObjectAPI.GetObjectInfo(bucket, object) objInfo, err = api.ObjectAPI.GetObjectInfo(bucket, object)
if err != nil { if err != nil {
errorIf(err, "GetObjectInfo failed.", nil) errorIf(err, "GetObjectInfo failed.", nil)
writeErrorResponse(w, r, ErrInternalError, r.URL.Path) writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
return return
} }
@ -675,27 +624,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req
} }
if err != nil { if err != nil {
errorIf(err, "PutObject failed.", nil) errorIf(err, "PutObject failed.", nil)
// Verify if the underlying error is signature mismatch. writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
if err == errSignatureMismatch {
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
return
}
switch err.(type) {
case StorageFull:
writeErrorResponse(w, r, ErrStorageFull, r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case BadDigest:
writeErrorResponse(w, r, ErrBadDigest, r.URL.Path)
case IncompleteBody:
writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path)
case ObjectExistsAsPrefix:
writeErrorResponse(w, r, ErrObjectExistsAsPrefix, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
if md5Sum != "" { if md5Sum != "" {
@ -734,20 +663,7 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r
uploadID, err := api.ObjectAPI.NewMultipartUpload(bucket, object) uploadID, err := api.ObjectAPI.NewMultipartUpload(bucket, object)
if err != nil { if err != nil {
errorIf(err, "NewMultipartUpload failed.", nil) errorIf(err, "NewMultipartUpload failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case StorageFull:
writeErrorResponse(w, r, ErrStorageFull, r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case ObjectNotFound:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
case ObjectNameInvalid:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
@ -847,22 +763,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
if err != nil { if err != nil {
errorIf(err, "PutObjectPart failed.", nil) errorIf(err, "PutObjectPart failed.", nil)
// Verify if the underlying error is signature mismatch. // Verify if the underlying error is signature mismatch.
if err == errSignatureMismatch { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
return
}
switch err.(type) {
case StorageFull:
writeErrorResponse(w, r, ErrStorageFull, r.URL.Path)
case InvalidUploadID:
writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path)
case BadDigest:
writeErrorResponse(w, r, ErrBadDigest, r.URL.Path)
case IncompleteBody:
writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
if partMD5 != "" { if partMD5 != "" {
@ -898,20 +799,7 @@ func (api objectAPIHandlers) AbortMultipartUploadHandler(w http.ResponseWriter,
uploadID, _, _, _ := getObjectResources(r.URL.Query()) uploadID, _, _, _ := getObjectResources(r.URL.Query())
if err := api.ObjectAPI.AbortMultipartUpload(bucket, object, uploadID); err != nil { if err := api.ObjectAPI.AbortMultipartUpload(bucket, object, uploadID); err != nil {
errorIf(err, "AbortMutlipartUpload failed.", nil) errorIf(err, "AbortMutlipartUpload failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case ObjectNotFound:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
case ObjectNameInvalid:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
case InvalidUploadID:
writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
writeSuccessNoContent(w) writeSuccessNoContent(w)
@ -957,22 +845,7 @@ func (api objectAPIHandlers) ListObjectPartsHandler(w http.ResponseWriter, r *ht
listPartsInfo, err := api.ObjectAPI.ListObjectParts(bucket, object, uploadID, partNumberMarker, maxParts) listPartsInfo, err := api.ObjectAPI.ListObjectParts(bucket, object, uploadID, partNumberMarker, maxParts)
if err != nil { if err != nil {
errorIf(err, "ListObjectParts failed.", nil) errorIf(err, "ListObjectParts failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case ObjectNotFound:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
case ObjectNameInvalid:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
case InvalidUploadID:
writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path)
case InvalidPart:
writeErrorResponse(w, r, ErrInvalidPart, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
response := generateListPartsResponse(listPartsInfo) response := generateListPartsResponse(listPartsInfo)
@ -1038,24 +911,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite
md5Sum, err = api.ObjectAPI.CompleteMultipartUpload(bucket, object, uploadID, completeParts) md5Sum, err = api.ObjectAPI.CompleteMultipartUpload(bucket, object, uploadID, completeParts)
if err != nil { if err != nil {
errorIf(err, "CompleteMultipartUpload failed.", nil) errorIf(err, "CompleteMultipartUpload failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case ObjectNotFound:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
case ObjectNameInvalid:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
case InvalidUploadID:
writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path)
case InvalidPart:
writeErrorResponse(w, r, ErrInvalidPart, r.URL.Path)
case IncompleteBody:
writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
// Get object location. // Get object location.
@ -1096,18 +952,7 @@ func (api objectAPIHandlers) DeleteObjectHandler(w http.ResponseWriter, r *http.
} }
if err := api.ObjectAPI.DeleteObject(bucket, object); err != nil { if err := api.ObjectAPI.DeleteObject(bucket, object); err != nil {
errorIf(err, "DeleteObject failed.", nil) errorIf(err, "DeleteObject failed.", nil)
switch err.(type) { writeErrorResponse(w, r, toAPIErrorCode(err), r.URL.Path)
case BucketNameInvalid:
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
case BucketNotFound:
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
case ObjectNotFound:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
case ObjectNameInvalid:
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
default:
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
}
return return
} }
writeSuccessNoContent(w) writeSuccessNoContent(w)

View File

@ -411,10 +411,10 @@ func writeWebErrorResponse(w http.ResponseWriter, err error) {
apiErrCode = ErrNoSuchKey apiErrCode = ErrNoSuchKey
case ObjectNameInvalid: case ObjectNameInvalid:
apiErrCode = ErrNoSuchKey apiErrCode = ErrNoSuchKey
case StorageInsufficientWriteResources: case InsufficientWriteQuorum:
apiErrCode = ErrInsufficientWriteResources apiErrCode = ErrWriteQuorum
case StorageInsufficientReadResources: case InsufficientReadQuorum:
apiErrCode = ErrInsufficientReadResources apiErrCode = ErrReadQuorum
default: default:
apiErrCode = ErrInternalError apiErrCode = ErrInternalError
} }

View File

@ -62,13 +62,12 @@ func (xl XL) listOnlineDisks(volume, path string) (onlineDisks []StorageAPI, mda
for _, err := range errs { for _, err := range errs {
if err == errFileNotFound { if err == errFileNotFound {
notFoundCount++ notFoundCount++
// If we have errors with file not found greater than allowed read
// quorum we return err as errFileNotFound.
if notFoundCount > len(xl.storageDisks)-xl.readQuorum {
return nil, xlMetaV1{}, false, errFileNotFound
}
} }
} }
// If we have errors with file not found equal to the number of disks.
if notFoundCount == len(xl.storageDisks) {
return nil, xlMetaV1{}, false, errFileNotFound
}
highestVersion := int64(0) highestVersion := int64(0)
onlineDisks = make([]StorageAPI, len(xl.storageDisks)) onlineDisks = make([]StorageAPI, len(xl.storageDisks))
// List all the file versions from partsMetadata list. // List all the file versions from partsMetadata list.

View File

@ -163,13 +163,17 @@ func (xl xlObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) {
} }
fi, err := xl.storage.StatFile(bucket, object) fi, err := xl.storage.StatFile(bucket, object)
if err != nil { if err != nil {
info, err := getMultipartObjectInfo(xl.storage, bucket, object) if err == errFileNotFound {
if err != nil { var info MultipartObjectInfo
return ObjectInfo{}, toObjectErr(err, bucket, object) info, err = getMultipartObjectInfo(xl.storage, bucket, object)
if err != nil {
return ObjectInfo{}, toObjectErr(err, bucket, object)
}
fi.Size = info.Size
fi.ModTime = info.ModTime
fi.MD5Sum = info.MD5Sum
} }
fi.Size = info.Size return ObjectInfo{}, toObjectErr(err, bucket, object)
fi.ModTime = info.ModTime
fi.MD5Sum = info.MD5Sum
} }
contentType := "application/octet-stream" contentType := "application/octet-stream"
if objectExt := filepath.Ext(object); objectExt != "" { if objectExt := filepath.Ext(object); objectExt != "" {