2020-09-20 05:09:58 +08:00
package s3err
2018-07-18 17:37:09 +08:00
import (
"encoding/xml"
2020-09-20 11:14:19 +08:00
"fmt"
2018-07-18 17:37:09 +08:00
"net/http"
)
// APIError structure
type APIError struct {
Code string
Description string
HTTPStatusCode int
}
// RESTErrorResponse - error response format
type RESTErrorResponse struct {
2021-06-11 12:55:13 +08:00
XMLName xml . Name ` xml:"Error" json:"-" `
Code string ` xml:"Code" json:"Code" `
Message string ` xml:"Message" json:"Message" `
Resource string ` xml:"Resource" json:"Resource" `
RequestID string ` xml:"RequestId" json:"RequestId" `
Key string ` xml:"Key,omitempty" json:"Key,omitempty" `
BucketName string ` xml:"BucketName,omitempty" json:"BucketName,omitempty" `
2020-09-20 11:14:19 +08:00
// Underlying HTTP status code for the returned error
StatusCode int ` xml:"-" json:"-" `
}
// Error - Returns S3 error string.
func ( e RESTErrorResponse ) Error ( ) string {
if e . Message == "" {
msg , ok := s3ErrorResponseMap [ e . Code ]
if ! ok {
msg = fmt . Sprintf ( "Error response code %s." , e . Code )
}
return msg
}
return e . Message
2018-07-18 17:37:09 +08:00
}
// ErrorCode type of error status.
type ErrorCode int
// Error codes, see full list at http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
const (
2018-07-22 16:15:11 +08:00
ErrNone ErrorCode = iota
2020-02-10 06:30:02 +08:00
ErrAccessDenied
2018-07-18 17:37:09 +08:00
ErrMethodNotAllowed
ErrBucketNotEmpty
ErrBucketAlreadyExists
ErrBucketAlreadyOwnedByYou
2018-07-19 16:43:27 +08:00
ErrNoSuchBucket
2022-02-03 22:17:05 +08:00
ErrNoSuchBucketPolicy
ErrNoSuchCORSConfiguration
2021-10-11 18:03:56 +08:00
ErrNoSuchLifecycleConfiguration
2020-06-11 22:53:15 +08:00
ErrNoSuchKey
2018-09-04 15:42:44 +08:00
ErrNoSuchUpload
2018-07-22 01:39:02 +08:00
ErrInvalidBucketName
ErrInvalidDigest
2018-07-22 16:14:36 +08:00
ErrInvalidMaxKeys
2018-09-04 15:42:44 +08:00
ErrInvalidMaxUploads
ErrInvalidMaxParts
2022-03-29 19:55:09 +08:00
ErrInvalidMaxDeleteObjects
2018-09-04 15:42:44 +08:00
ErrInvalidPartNumberMarker
ErrInvalidPart
2018-07-18 17:37:09 +08:00
ErrInternalError
2020-01-31 16:11:08 +08:00
ErrInvalidCopyDest
ErrInvalidCopySource
2020-10-03 13:21:51 +08:00
ErrInvalidTag
2020-02-10 06:30:02 +08:00
ErrAuthHeaderEmpty
ErrSignatureVersionNotSupported
2020-09-20 11:14:19 +08:00
ErrMalformedPOSTRequest
ErrPOSTFileRequired
ErrPostPolicyConditionInvalidFormat
ErrEntityTooSmall
ErrEntityTooLarge
2020-02-10 06:30:02 +08:00
ErrMissingFields
ErrMissingCredTag
ErrCredMalformed
2020-02-26 06:38:36 +08:00
ErrMalformedXML
2020-02-10 06:30:02 +08:00
ErrMalformedDate
ErrMalformedPresignedDate
ErrMalformedCredentialDate
ErrMissingSignHeadersTag
ErrMissingSignTag
ErrUnsignedHeaders
ErrInvalidQueryParams
ErrInvalidQuerySignatureAlgo
ErrExpiredPresignRequest
ErrMalformedExpires
ErrNegativeExpires
ErrMaximumExpires
ErrSignatureDoesNotMatch
ErrContentSHA256Mismatch
ErrInvalidAccessKeyID
ErrRequestNotReadyYet
ErrMissingDateHeader
2020-02-10 08:02:05 +08:00
ErrInvalidRequest
2021-05-22 05:08:47 +08:00
ErrAuthNotSetup
2018-07-22 16:14:36 +08:00
ErrNotImplemented
2021-05-24 19:59:44 +08:00
ErrPreconditionFailed
2020-10-21 01:25:16 +08:00
ErrExistingObjectIsDirectory
2022-02-04 08:28:37 +08:00
ErrExistingObjectIsFile
2018-07-18 17:37:09 +08:00
)
// error code to APIError structure, these fields carry respective
// descriptions for all the error responses.
var errorCodeResponse = map [ ErrorCode ] APIError {
2020-02-10 06:30:02 +08:00
ErrAccessDenied : {
Code : "AccessDenied" ,
Description : "Access Denied." ,
HTTPStatusCode : http . StatusForbidden ,
} ,
2018-07-18 17:37:09 +08:00
ErrMethodNotAllowed : {
Code : "MethodNotAllowed" ,
Description : "The specified method is not allowed against this resource." ,
HTTPStatusCode : http . StatusMethodNotAllowed ,
} ,
ErrBucketNotEmpty : {
Code : "BucketNotEmpty" ,
Description : "The bucket you tried to delete is not empty" ,
HTTPStatusCode : http . StatusConflict ,
} ,
ErrBucketAlreadyExists : {
Code : "BucketAlreadyExists" ,
2021-05-13 13:30:39 +08:00
Description : "The requested bucket name is not available. The bucket name can not be an existing collection, and the bucket namespace is shared by all users of the system. Please select a different name and try again." ,
2018-07-18 17:37:09 +08:00
HTTPStatusCode : http . StatusConflict ,
} ,
ErrBucketAlreadyOwnedByYou : {
Code : "BucketAlreadyOwnedByYou" ,
Description : "Your previous request to create the named bucket succeeded and you already own it." ,
HTTPStatusCode : http . StatusConflict ,
} ,
ErrInvalidBucketName : {
Code : "InvalidBucketName" ,
Description : "The specified bucket is not valid." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2018-07-22 01:39:02 +08:00
ErrInvalidDigest : {
Code : "InvalidDigest" ,
Description : "The Content-Md5 you specified is not valid." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2018-09-04 15:42:44 +08:00
ErrInvalidMaxUploads : {
Code : "InvalidArgument" ,
Description : "Argument max-uploads must be an integer between 0 and 2147483647" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2018-07-22 16:14:36 +08:00
ErrInvalidMaxKeys : {
Code : "InvalidArgument" ,
Description : "Argument maxKeys must be an integer between 0 and 2147483647" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2018-09-04 15:42:44 +08:00
ErrInvalidMaxParts : {
Code : "InvalidArgument" ,
Description : "Argument max-parts must be an integer between 0 and 2147483647" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2022-03-29 19:55:09 +08:00
ErrInvalidMaxDeleteObjects : {
Code : "InvalidArgument" ,
Description : "Argument objects must be contains a list of up to 1000 keys" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2018-09-04 15:42:44 +08:00
ErrInvalidPartNumberMarker : {
Code : "InvalidArgument" ,
Description : "Argument partNumberMarker must be an integer." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2018-07-19 16:43:27 +08:00
ErrNoSuchBucket : {
Code : "NoSuchBucket" ,
Description : "The specified bucket does not exist" ,
HTTPStatusCode : http . StatusNotFound ,
} ,
2022-02-03 22:17:05 +08:00
ErrNoSuchBucketPolicy : {
Code : "NoSuchBucketPolicy" ,
Description : "The bucket policy does not exist" ,
HTTPStatusCode : http . StatusNotFound ,
} ,
ErrNoSuchCORSConfiguration : {
Code : "NoSuchCORSConfiguration" ,
Description : "The CORS configuration does not exist" ,
HTTPStatusCode : http . StatusNotFound ,
} ,
2021-10-11 18:03:56 +08:00
ErrNoSuchLifecycleConfiguration : {
Code : "NoSuchLifecycleConfiguration" ,
Description : "The lifecycle configuration does not exist" ,
HTTPStatusCode : http . StatusNotFound ,
} ,
2020-06-11 22:53:15 +08:00
ErrNoSuchKey : {
Code : "NoSuchKey" ,
Description : "The specified key does not exist." ,
HTTPStatusCode : http . StatusNotFound ,
} ,
2018-09-04 15:42:44 +08:00
ErrNoSuchUpload : {
Code : "NoSuchUpload" ,
Description : "The specified multipart upload does not exist. The upload ID may be invalid, or the upload may have been aborted or completed." ,
HTTPStatusCode : http . StatusNotFound ,
} ,
2018-07-18 17:37:09 +08:00
ErrInternalError : {
Code : "InternalError" ,
Description : "We encountered an internal error, please try again." ,
HTTPStatusCode : http . StatusInternalServerError ,
} ,
2018-09-12 15:46:12 +08:00
2018-09-04 15:42:44 +08:00
ErrInvalidPart : {
Code : "InvalidPart" ,
Description : "One or more of the specified parts could not be found. The part may not have been uploaded, or the specified entity tag may not match the part's entity tag." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2020-01-31 16:11:08 +08:00
ErrInvalidCopyDest : {
Code : "InvalidRequest" ,
Description : "This copy request is illegal because it is trying to copy an object to itself without changing the object's metadata, storage class, website redirect location or encryption attributes." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrInvalidCopySource : {
Code : "InvalidArgument" ,
Description : "Copy Source must mention the source bucket and key: sourcebucket/sourcekey." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2020-10-03 13:21:51 +08:00
ErrInvalidTag : {
2021-10-20 19:01:06 +08:00
Code : "InvalidTag" ,
2020-10-03 13:21:51 +08:00
Description : "The Tag value you have provided is invalid" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2020-02-26 06:38:36 +08:00
ErrMalformedXML : {
Code : "MalformedXML" ,
Description : "The XML you provided was not well-formed or did not validate against our published schema." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2020-02-10 06:30:02 +08:00
ErrAuthHeaderEmpty : {
Code : "InvalidArgument" ,
Description : "Authorization header is invalid -- one and only one ' ' (space) required." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrSignatureVersionNotSupported : {
Code : "InvalidRequest" ,
Description : "The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2020-09-20 11:14:19 +08:00
ErrMalformedPOSTRequest : {
Code : "MalformedPOSTRequest" ,
Description : "The body of your POST request is not well-formed multipart/form-data." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrPOSTFileRequired : {
Code : "InvalidArgument" ,
Description : "POST requires exactly one file upload per request." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrPostPolicyConditionInvalidFormat : {
Code : "PostPolicyInvalidKeyName" ,
Description : "Invalid according to Policy: Policy Condition failed" ,
HTTPStatusCode : http . StatusForbidden ,
} ,
ErrEntityTooSmall : {
Code : "EntityTooSmall" ,
Description : "Your proposed upload is smaller than the minimum allowed object size." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrEntityTooLarge : {
Code : "EntityTooLarge" ,
Description : "Your proposed upload exceeds the maximum allowed object size." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2020-02-10 06:30:02 +08:00
ErrMissingFields : {
Code : "MissingFields" ,
Description : "Missing fields in request." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrMissingCredTag : {
Code : "InvalidRequest" ,
Description : "Missing Credential field for this request." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrCredMalformed : {
Code : "AuthorizationQueryParametersError" ,
Description : "Error parsing the X-Amz-Credential parameter; the Credential is mal-formed; expecting \"<YOUR-AKID>/YYYYMMDD/REGION/SERVICE/aws4_request\"." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrMalformedDate : {
Code : "MalformedDate" ,
Description : "Invalid date format header, expected to be in ISO8601, RFC1123 or RFC1123Z time format." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrMalformedPresignedDate : {
Code : "AuthorizationQueryParametersError" ,
Description : "X-Amz-Date must be in the ISO8601 Long Format \"yyyyMMdd'T'HHmmss'Z'\"" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrMissingSignHeadersTag : {
Code : "InvalidArgument" ,
Description : "Signature header missing SignedHeaders field." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrMissingSignTag : {
Code : "AccessDenied" ,
Description : "Signature header missing Signature field." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrUnsignedHeaders : {
Code : "AccessDenied" ,
Description : "There were headers present in the request which were not signed" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrInvalidQueryParams : {
Code : "AuthorizationQueryParametersError" ,
Description : "Query-string authentication version 4 requires the X-Amz-Algorithm, X-Amz-Credential, X-Amz-Signature, X-Amz-Date, X-Amz-SignedHeaders, and X-Amz-Expires parameters." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrInvalidQuerySignatureAlgo : {
Code : "AuthorizationQueryParametersError" ,
Description : "X-Amz-Algorithm only supports \"AWS4-HMAC-SHA256\"." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrExpiredPresignRequest : {
Code : "AccessDenied" ,
Description : "Request has expired" ,
HTTPStatusCode : http . StatusForbidden ,
} ,
ErrMalformedExpires : {
Code : "AuthorizationQueryParametersError" ,
Description : "X-Amz-Expires should be a number" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrNegativeExpires : {
Code : "AuthorizationQueryParametersError" ,
Description : "X-Amz-Expires must be non-negative" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrMaximumExpires : {
Code : "AuthorizationQueryParametersError" ,
Description : "X-Amz-Expires must be less than a week (in seconds); that is, the given X-Amz-Expires must be less than 604800 seconds" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrInvalidAccessKeyID : {
Code : "InvalidAccessKeyId" ,
Description : "The access key ID you provided does not exist in our records." ,
HTTPStatusCode : http . StatusForbidden ,
} ,
ErrRequestNotReadyYet : {
Code : "AccessDenied" ,
Description : "Request is not valid yet" ,
HTTPStatusCode : http . StatusForbidden ,
} ,
ErrSignatureDoesNotMatch : {
Code : "SignatureDoesNotMatch" ,
Description : "The request signature we calculated does not match the signature you provided. Check your key and signing method." ,
HTTPStatusCode : http . StatusForbidden ,
} ,
ErrContentSHA256Mismatch : {
Code : "XAmzContentSHA256Mismatch" ,
Description : "The provided 'x-amz-content-sha256' header does not match what was computed." ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
ErrMissingDateHeader : {
Code : "AccessDenied" ,
Description : "AWS authentication requires a valid Date or x-amz-date header" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2020-02-10 08:02:05 +08:00
ErrInvalidRequest : {
Code : "InvalidRequest" ,
Description : "Invalid Request" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2021-05-24 19:59:44 +08:00
ErrAuthNotSetup : {
2021-05-22 05:08:47 +08:00
Code : "InvalidRequest" ,
Description : "Signed request requires setting up SeaweedFS S3 authentication" ,
HTTPStatusCode : http . StatusBadRequest ,
} ,
2018-07-22 16:14:36 +08:00
ErrNotImplemented : {
Code : "NotImplemented" ,
Description : "A header you provided implies functionality that is not implemented" ,
HTTPStatusCode : http . StatusNotImplemented ,
} ,
2021-05-24 19:59:44 +08:00
ErrPreconditionFailed : {
Code : "PreconditionFailed" ,
Description : "At least one of the pre-conditions you specified did not hold" ,
HTTPStatusCode : http . StatusPreconditionFailed ,
} ,
2020-10-21 01:25:16 +08:00
ErrExistingObjectIsDirectory : {
Code : "ExistingObjectIsDirectory" ,
Description : "Existing Object is a directory." ,
HTTPStatusCode : http . StatusConflict ,
} ,
2022-02-04 08:28:37 +08:00
ErrExistingObjectIsFile : {
Code : "ExistingObjectIsFile" ,
Description : "Existing Object is a file." ,
HTTPStatusCode : http . StatusConflict ,
} ,
2018-07-18 17:37:09 +08:00
}
2020-09-20 05:09:58 +08:00
// GetAPIError provides API Error for input API error code.
func GetAPIError ( code ErrorCode ) APIError {
2018-07-18 17:37:09 +08:00
return errorCodeResponse [ code ]
}