mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
handlers: overhaul entire writErrorResponse, simplify. (#1472)
This commit is contained in:
parent
ba5805e60a
commit
17868ccd7f
@ -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]
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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 != "" {
|
||||||
|
Loading…
Reference in New Issue
Block a user