mirror of
https://github.com/minio/minio.git
synced 2025-01-12 15:33:22 -05:00
Merge pull request #1209 from harshavardhana/err-naming
error: Add proper prefixes for s3Error codes.
This commit is contained in:
commit
b5c77b641d
182
api-errors.go
182
api-errors.go
@ -40,269 +40,275 @@ type APIErrorResponse struct {
|
|||||||
HostID string `xml:"HostId"`
|
HostID string `xml:"HostId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// APIErrorCode type of error status.
|
||||||
|
type APIErrorCode int
|
||||||
|
|
||||||
// Error codes, non exhaustive list - http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
|
// Error codes, non exhaustive list - http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
|
||||||
const (
|
const (
|
||||||
None = iota
|
ErrNone APIErrorCode = iota
|
||||||
AccessDenied
|
ErrAccessDenied
|
||||||
BadDigest
|
ErrBadDigest
|
||||||
BucketAlreadyExists
|
ErrBucketAlreadyExists
|
||||||
EntityTooSmall
|
ErrEntityTooSmall
|
||||||
EntityTooLarge
|
ErrEntityTooLarge
|
||||||
IncompleteBody
|
ErrIncompleteBody
|
||||||
InternalError
|
ErrInternalError
|
||||||
InvalidAccessKeyID
|
ErrInvalidAccessKeyID
|
||||||
InvalidBucketName
|
ErrInvalidBucketName
|
||||||
InvalidDigest
|
ErrInvalidDigest
|
||||||
InvalidRange
|
ErrInvalidRange
|
||||||
InvalidMaxKeys
|
ErrInvalidMaxKeys
|
||||||
InvalidMaxUploads
|
ErrInvalidMaxUploads
|
||||||
InvalidMaxParts
|
ErrInvalidMaxParts
|
||||||
InvalidPartNumberMarker
|
ErrInvalidPartNumberMarker
|
||||||
InvalidRequestBody
|
ErrInvalidRequestBody
|
||||||
InvalidCopySource
|
ErrInvalidCopySource
|
||||||
InvalidCopyDest
|
ErrInvalidCopyDest
|
||||||
InvalidPolicyDocument
|
ErrInvalidPolicyDocument
|
||||||
MalformedXML
|
ErrMalformedXML
|
||||||
MissingContentLength
|
ErrMissingContentLength
|
||||||
MissingContentMD5
|
ErrMissingContentMD5
|
||||||
MissingRequestBodyError
|
ErrMissingRequestBodyError
|
||||||
NoSuchBucket
|
ErrNoSuchBucket
|
||||||
NoSuchBucketPolicy
|
ErrNoSuchBucketPolicy
|
||||||
NoSuchKey
|
ErrNoSuchKey
|
||||||
NoSuchUpload
|
ErrNoSuchUpload
|
||||||
NotImplemented
|
ErrNotImplemented
|
||||||
RequestTimeTooSkewed
|
ErrRequestTimeTooSkewed
|
||||||
SignatureDoesNotMatch
|
ErrSignatureDoesNotMatch
|
||||||
MethodNotAllowed
|
ErrMethodNotAllowed
|
||||||
InvalidPart
|
ErrInvalidPart
|
||||||
InvalidPartOrder
|
ErrInvalidPartOrder
|
||||||
AuthorizationHeaderMalformed
|
ErrAuthorizationHeaderMalformed
|
||||||
MalformedPOSTRequest
|
ErrMalformedPOSTRequest
|
||||||
SignatureVersionNotSupported
|
ErrSignatureVersionNotSupported
|
||||||
BucketNotEmpty
|
ErrBucketNotEmpty
|
||||||
RootPathFull
|
ErrRootPathFull
|
||||||
ObjectExistsAsPrefix
|
ErrObjectExistsAsPrefix
|
||||||
AllAccessDisabled
|
ErrAllAccessDisabled
|
||||||
MalformedPolicy
|
ErrMalformedPolicy
|
||||||
|
// Add new error codes here.
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIError code to Error structure map
|
// error code to APIError structure, these fields carry respective
|
||||||
var errorCodeResponse = map[int]APIError{
|
// descriptions for all the error responses.
|
||||||
InvalidCopyDest: {
|
var errorCodeResponse = map[APIErrorCode]APIError{
|
||||||
|
ErrInvalidCopyDest: {
|
||||||
Code: "InvalidRequest",
|
Code: "InvalidRequest",
|
||||||
Description: "This copy request is illegal because it is trying to copy an object to itself.",
|
Description: "This copy request is illegal because it is trying to copy an object to itself.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InvalidCopySource: {
|
ErrInvalidCopySource: {
|
||||||
Code: "InvalidArgument",
|
Code: "InvalidArgument",
|
||||||
Description: "Copy Source must mention the source bucket and key: sourcebucket/sourcekey.",
|
Description: "Copy Source must mention the source bucket and key: sourcebucket/sourcekey.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InvalidRequestBody: {
|
ErrInvalidRequestBody: {
|
||||||
Code: "InvalidArgument",
|
Code: "InvalidArgument",
|
||||||
Description: "Body shouldn't be set for this request.",
|
Description: "Body shouldn't be set for this request.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InvalidMaxUploads: {
|
ErrInvalidMaxUploads: {
|
||||||
Code: "InvalidArgument",
|
Code: "InvalidArgument",
|
||||||
Description: "Argument maxUploads must be an integer between 0 and 2147483647.",
|
Description: "Argument maxUploads must be an integer between 0 and 2147483647.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InvalidMaxKeys: {
|
ErrInvalidMaxKeys: {
|
||||||
Code: "InvalidArgument",
|
Code: "InvalidArgument",
|
||||||
Description: "Argument maxKeys must be an integer between 0 and 2147483647.",
|
Description: "Argument maxKeys must be an integer between 0 and 2147483647.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InvalidMaxParts: {
|
ErrInvalidMaxParts: {
|
||||||
Code: "InvalidArgument",
|
Code: "InvalidArgument",
|
||||||
Description: "Argument maxParts must be an integer between 1 and 10000.",
|
Description: "Argument maxParts must be an integer between 1 and 10000.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InvalidPartNumberMarker: {
|
ErrInvalidPartNumberMarker: {
|
||||||
Code: "InvalidArgument",
|
Code: "InvalidArgument",
|
||||||
Description: "Argument partNumberMarker must be an integer.",
|
Description: "Argument partNumberMarker must be an integer.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InvalidPolicyDocument: {
|
ErrInvalidPolicyDocument: {
|
||||||
Code: "InvalidPolicyDocument",
|
Code: "InvalidPolicyDocument",
|
||||||
Description: "The content of the form does not meet the conditions specified in the policy document.",
|
Description: "The content of the form does not meet the conditions specified in the policy document.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
AccessDenied: {
|
ErrAccessDenied: {
|
||||||
Code: "AccessDenied",
|
Code: "AccessDenied",
|
||||||
Description: "Access Denied.",
|
Description: "Access Denied.",
|
||||||
HTTPStatusCode: http.StatusForbidden,
|
HTTPStatusCode: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
BadDigest: {
|
ErrBadDigest: {
|
||||||
Code: "BadDigest",
|
Code: "BadDigest",
|
||||||
Description: "The Content-Md5 you specified did not match what we received.",
|
Description: "The Content-Md5 you specified did not match what we received.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
BucketAlreadyExists: {
|
ErrBucketAlreadyExists: {
|
||||||
Code: "BucketAlreadyExists",
|
Code: "BucketAlreadyExists",
|
||||||
Description: "The requested bucket name is not available.",
|
Description: "The requested bucket name is not available.",
|
||||||
HTTPStatusCode: http.StatusConflict,
|
HTTPStatusCode: http.StatusConflict,
|
||||||
},
|
},
|
||||||
EntityTooSmall: {
|
ErrEntityTooSmall: {
|
||||||
Code: "EntityTooSmall",
|
Code: "EntityTooSmall",
|
||||||
Description: "Your proposed upload is smaller than the minimum allowed object size.",
|
Description: "Your proposed upload is smaller than the minimum allowed object size.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
EntityTooLarge: {
|
ErrEntityTooLarge: {
|
||||||
Code: "EntityTooLarge",
|
Code: "EntityTooLarge",
|
||||||
Description: "Your proposed upload exceeds the maximum allowed object size.",
|
Description: "Your proposed upload exceeds the maximum allowed object size.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
IncompleteBody: {
|
ErrIncompleteBody: {
|
||||||
Code: "IncompleteBody",
|
Code: "IncompleteBody",
|
||||||
Description: "You did not provide the number of bytes specified by the Content-Length HTTP header.",
|
Description: "You did not provide the number of bytes specified by the Content-Length HTTP header.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InternalError: {
|
ErrInternalError: {
|
||||||
Code: "InternalError",
|
Code: "InternalError",
|
||||||
Description: "We encountered an internal error, please try again.",
|
Description: "We encountered an internal error, please try again.",
|
||||||
HTTPStatusCode: http.StatusInternalServerError,
|
HTTPStatusCode: http.StatusInternalServerError,
|
||||||
},
|
},
|
||||||
InvalidAccessKeyID: {
|
ErrInvalidAccessKeyID: {
|
||||||
Code: "InvalidAccessKeyID",
|
Code: "InvalidAccessKeyID",
|
||||||
Description: "The access key ID you provided does not exist in our records.",
|
Description: "The access key ID you provided does not exist in our records.",
|
||||||
HTTPStatusCode: http.StatusForbidden,
|
HTTPStatusCode: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
InvalidBucketName: {
|
ErrInvalidBucketName: {
|
||||||
Code: "InvalidBucketName",
|
Code: "InvalidBucketName",
|
||||||
Description: "The specified bucket is not valid.",
|
Description: "The specified bucket is not valid.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InvalidDigest: {
|
ErrInvalidDigest: {
|
||||||
Code: "InvalidDigest",
|
Code: "InvalidDigest",
|
||||||
Description: "The Content-Md5 you specified is not valid.",
|
Description: "The Content-Md5 you specified is not valid.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InvalidRange: {
|
ErrInvalidRange: {
|
||||||
Code: "InvalidRange",
|
Code: "InvalidRange",
|
||||||
Description: "The requested range cannot be satisfied.",
|
Description: "The requested range cannot be satisfied.",
|
||||||
HTTPStatusCode: http.StatusRequestedRangeNotSatisfiable,
|
HTTPStatusCode: http.StatusRequestedRangeNotSatisfiable,
|
||||||
},
|
},
|
||||||
MalformedXML: {
|
ErrMalformedXML: {
|
||||||
Code: "MalformedXML",
|
Code: "MalformedXML",
|
||||||
Description: "The XML you provided was not well-formed or did not validate against our published schema.",
|
Description: "The XML you provided was not well-formed or did not validate against our published schema.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
MissingContentLength: {
|
ErrMissingContentLength: {
|
||||||
Code: "MissingContentLength",
|
Code: "MissingContentLength",
|
||||||
Description: "You must provide the Content-Length HTTP header.",
|
Description: "You must provide the Content-Length HTTP header.",
|
||||||
HTTPStatusCode: http.StatusLengthRequired,
|
HTTPStatusCode: http.StatusLengthRequired,
|
||||||
},
|
},
|
||||||
MissingContentMD5: {
|
ErrMissingContentMD5: {
|
||||||
Code: "MissingContentMD5",
|
Code: "MissingContentMD5",
|
||||||
Description: "Missing required header for this request: Content-Md5.",
|
Description: "Missing required header for this request: Content-Md5.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
MissingRequestBodyError: {
|
ErrMissingRequestBodyError: {
|
||||||
Code: "MissingRequestBodyError",
|
Code: "MissingRequestBodyError",
|
||||||
Description: "Request body is empty.",
|
Description: "Request body is empty.",
|
||||||
HTTPStatusCode: http.StatusLengthRequired,
|
HTTPStatusCode: http.StatusLengthRequired,
|
||||||
},
|
},
|
||||||
NoSuchBucket: {
|
ErrNoSuchBucket: {
|
||||||
Code: "NoSuchBucket",
|
Code: "NoSuchBucket",
|
||||||
Description: "The specified bucket does not exist.",
|
Description: "The specified bucket does not exist.",
|
||||||
HTTPStatusCode: http.StatusNotFound,
|
HTTPStatusCode: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
NoSuchBucketPolicy: {
|
ErrNoSuchBucketPolicy: {
|
||||||
Code: "NoSuchBucketPolicy",
|
Code: "NoSuchBucketPolicy",
|
||||||
Description: "The specified bucket does not have a bucket policy.",
|
Description: "The specified bucket does not have a bucket policy.",
|
||||||
HTTPStatusCode: http.StatusNotFound,
|
HTTPStatusCode: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
NoSuchKey: {
|
ErrNoSuchKey: {
|
||||||
Code: "NoSuchKey",
|
Code: "NoSuchKey",
|
||||||
Description: "The specified key does not exist.",
|
Description: "The specified key does not exist.",
|
||||||
HTTPStatusCode: http.StatusNotFound,
|
HTTPStatusCode: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
NoSuchUpload: {
|
ErrNoSuchUpload: {
|
||||||
Code: "NoSuchUpload",
|
Code: "NoSuchUpload",
|
||||||
Description: "The specified multipart upload does not exist.",
|
Description: "The specified multipart upload does not exist.",
|
||||||
HTTPStatusCode: http.StatusNotFound,
|
HTTPStatusCode: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
NotImplemented: {
|
ErrNotImplemented: {
|
||||||
Code: "NotImplemented",
|
Code: "NotImplemented",
|
||||||
Description: "A header you provided implies functionality that is not implemented.",
|
Description: "A header you provided implies functionality that is not implemented.",
|
||||||
HTTPStatusCode: http.StatusNotImplemented,
|
HTTPStatusCode: http.StatusNotImplemented,
|
||||||
},
|
},
|
||||||
RequestTimeTooSkewed: {
|
ErrRequestTimeTooSkewed: {
|
||||||
Code: "RequestTimeTooSkewed",
|
Code: "RequestTimeTooSkewed",
|
||||||
Description: "The difference between the request time and the server's time is too large.",
|
Description: "The difference between the request time and the server's time is too large.",
|
||||||
HTTPStatusCode: http.StatusForbidden,
|
HTTPStatusCode: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
SignatureDoesNotMatch: {
|
ErrSignatureDoesNotMatch: {
|
||||||
Code: "SignatureDoesNotMatch",
|
Code: "SignatureDoesNotMatch",
|
||||||
Description: "The request signature we calculated does not match the signature you provided.",
|
Description: "The request signature we calculated does not match the signature you provided.",
|
||||||
HTTPStatusCode: http.StatusForbidden,
|
HTTPStatusCode: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
MethodNotAllowed: {
|
ErrMethodNotAllowed: {
|
||||||
Code: "MethodNotAllowed",
|
Code: "MethodNotAllowed",
|
||||||
Description: "The specified method is not allowed against this resource.",
|
Description: "The specified method is not allowed against this resource.",
|
||||||
HTTPStatusCode: http.StatusMethodNotAllowed,
|
HTTPStatusCode: http.StatusMethodNotAllowed,
|
||||||
},
|
},
|
||||||
InvalidPart: {
|
ErrInvalidPart: {
|
||||||
Code: "InvalidPart",
|
Code: "InvalidPart",
|
||||||
Description: "One or more of the specified parts could not be found.",
|
Description: "One or more of the specified parts could not be found.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
InvalidPartOrder: {
|
ErrInvalidPartOrder: {
|
||||||
Code: "InvalidPartOrder",
|
Code: "InvalidPartOrder",
|
||||||
Description: "The list of parts was not in ascending order. The parts list must be specified in order by part number.",
|
Description: "The list of parts was not in ascending order. The parts list must be specified in order by part number.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
AuthorizationHeaderMalformed: {
|
ErrAuthorizationHeaderMalformed: {
|
||||||
Code: "AuthorizationHeaderMalformed",
|
Code: "AuthorizationHeaderMalformed",
|
||||||
Description: "The authorization header is malformed; the region is wrong; expecting 'us-east-1'.",
|
Description: "The authorization header is malformed; the region is wrong; expecting 'us-east-1'.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
MalformedPOSTRequest: {
|
ErrMalformedPOSTRequest: {
|
||||||
Code: "MalformedPOSTRequest",
|
Code: "MalformedPOSTRequest",
|
||||||
Description: "The body of your POST request is not well-formed multipart/form-data.",
|
Description: "The body of your POST request is not well-formed multipart/form-data.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
SignatureVersionNotSupported: {
|
ErrSignatureVersionNotSupported: {
|
||||||
Code: "InvalidRequest",
|
Code: "InvalidRequest",
|
||||||
Description: "The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.",
|
Description: "The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
BucketNotEmpty: {
|
ErrBucketNotEmpty: {
|
||||||
Code: "BucketNotEmpty",
|
Code: "BucketNotEmpty",
|
||||||
Description: "The bucket you tried to delete is not empty.",
|
Description: "The bucket you tried to delete is not empty.",
|
||||||
HTTPStatusCode: http.StatusConflict,
|
HTTPStatusCode: http.StatusConflict,
|
||||||
},
|
},
|
||||||
RootPathFull: {
|
ErrRootPathFull: {
|
||||||
Code: "RootPathFull",
|
Code: "RootPathFull",
|
||||||
Description: "Root path has reached its minimum free disk threshold. Please delete few objects to proceed.",
|
Description: "Root path has reached its minimum free disk threshold. Please delete few objects to proceed.",
|
||||||
HTTPStatusCode: http.StatusInternalServerError,
|
HTTPStatusCode: http.StatusInternalServerError,
|
||||||
},
|
},
|
||||||
ObjectExistsAsPrefix: {
|
ErrObjectExistsAsPrefix: {
|
||||||
Code: "ObjectExistsAsPrefix",
|
Code: "ObjectExistsAsPrefix",
|
||||||
Description: "An object already exists as your prefix, choose a different prefix to proceed.",
|
Description: "An object already exists as your prefix, choose a different prefix to proceed.",
|
||||||
HTTPStatusCode: http.StatusConflict,
|
HTTPStatusCode: http.StatusConflict,
|
||||||
},
|
},
|
||||||
AllAccessDisabled: {
|
ErrAllAccessDisabled: {
|
||||||
Code: "AllAccessDisabled",
|
Code: "AllAccessDisabled",
|
||||||
Description: "All access to this bucket has been disabled.",
|
Description: "All access to this bucket has been disabled.",
|
||||||
HTTPStatusCode: http.StatusForbidden,
|
HTTPStatusCode: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
MalformedPolicy: {
|
ErrMalformedPolicy: {
|
||||||
Code: "MalformedPolicy",
|
Code: "MalformedPolicy",
|
||||||
Description: "Policy has invalid resource",
|
Description: "Policy has invalid resource",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
|
// Add your error structure here.
|
||||||
}
|
}
|
||||||
|
|
||||||
// errorCodeError provides errorCode to Error. It returns empty if the code provided is unknown
|
// getAPIError provides API Error for input API error code.
|
||||||
func getErrorCode(code int) APIError {
|
func getAPIError(code APIErrorCode) APIError {
|
||||||
return errorCodeResponse[code]
|
return errorCodeResponse[code]
|
||||||
}
|
}
|
||||||
|
|
||||||
// getErrorResponse gets in standard error and resource value and
|
// getErrorResponse gets in standard error and resource value and
|
||||||
// provides a encodable populated response values
|
// provides a encodable populated response values
|
||||||
func getErrorResponse(err APIError, resource string) APIErrorResponse {
|
func getAPIErrorResponse(err APIError, resource string) APIErrorResponse {
|
||||||
var data = APIErrorResponse{}
|
var data = APIErrorResponse{}
|
||||||
data.Code = err.Code
|
data.Code = err.Code
|
||||||
data.Message = err.Description
|
data.Message = err.Description
|
||||||
|
@ -423,10 +423,10 @@ func writeSuccessNoContent(w http.ResponseWriter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeErrorRespone write error headers
|
// writeErrorRespone write error headers
|
||||||
func writeErrorResponse(w http.ResponseWriter, req *http.Request, errorType int, resource string) {
|
func writeErrorResponse(w http.ResponseWriter, req *http.Request, errorCode APIErrorCode, resource string) {
|
||||||
error := getErrorCode(errorType)
|
error := getAPIError(errorCode)
|
||||||
// generate error response
|
// generate error response
|
||||||
errorResponse := getErrorResponse(error, resource)
|
errorResponse := getAPIErrorResponse(error, resource)
|
||||||
encodedErrorResponse := encodeResponse(errorResponse)
|
encodedErrorResponse := encodeResponse(errorResponse)
|
||||||
// set common headers
|
// set common headers
|
||||||
setCommonHeaders(w)
|
setCommonHeaders(w)
|
||||||
|
@ -106,31 +106,31 @@ func getRequestAuthType(r *http.Request) authType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify if request has valid AWS Signature Version '4'.
|
// Verify if request has valid AWS Signature Version '4'.
|
||||||
func isSignV4ReqAuthenticated(sign *signature4.Sign, r *http.Request) (match bool, s3Error int) {
|
func isReqAuthenticated(sign *signature4.Sign, r *http.Request) (s3Error APIErrorCode) {
|
||||||
auth := sign.SetHTTPRequestToVerify(r)
|
auth := sign.SetHTTPRequestToVerify(r)
|
||||||
if isRequestSignatureV4(r) {
|
if isRequestSignatureV4(r) {
|
||||||
dummyPayload := sha256.Sum256([]byte(""))
|
dummyPayload := sha256.Sum256([]byte(""))
|
||||||
ok, err := auth.DoesSignatureMatch(hex.EncodeToString(dummyPayload[:]))
|
ok, err := auth.DoesSignatureMatch(hex.EncodeToString(dummyPayload[:]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "Signature verification failed.", nil)
|
errorIf(err.Trace(), "Signature verification failed.", nil)
|
||||||
return false, InternalError
|
return ErrInternalError
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, SignatureDoesNotMatch
|
return ErrSignatureDoesNotMatch
|
||||||
}
|
}
|
||||||
return ok, None
|
return ErrNone
|
||||||
} else if isRequestPresignedSignatureV4(r) {
|
} else if isRequestPresignedSignatureV4(r) {
|
||||||
ok, err := auth.DoesPresignedSignatureMatch()
|
ok, err := auth.DoesPresignedSignatureMatch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "Presigned signature verification failed.", nil)
|
errorIf(err.Trace(), "Presigned signature verification failed.", nil)
|
||||||
return false, InternalError
|
return ErrInternalError
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, SignatureDoesNotMatch
|
return ErrSignatureDoesNotMatch
|
||||||
}
|
}
|
||||||
return ok, None
|
return ErrNone
|
||||||
}
|
}
|
||||||
return false, AccessDenied
|
return ErrAccessDenied
|
||||||
}
|
}
|
||||||
|
|
||||||
// authHandler - handles all the incoming authorization headers and
|
// authHandler - handles all the incoming authorization headers and
|
||||||
@ -160,7 +160,7 @@ func (a authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
a.handler.ServeHTTP(w, r)
|
a.handler.ServeHTTP(w, r)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, SignatureVersionNotSupported, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureVersionNotSupported, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,26 +38,26 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
func enforceBucketPolicy(action string, bucket string, reqURL *url.URL) (isAllowed bool, s3Error int) {
|
func enforceBucketPolicy(action string, bucket string, reqURL *url.URL) (s3Error APIErrorCode) {
|
||||||
// Read saved bucket policy.
|
// Read saved bucket policy.
|
||||||
policy, err := readBucketPolicy(bucket)
|
policy, err := readBucketPolicy(bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(bucket), "GetBucketPolicy failed.", nil)
|
errorIf(err.Trace(bucket), "GetBucketPolicy failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
return false, NoSuchBucket
|
return ErrNoSuchBucket
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
return false, InvalidBucketName
|
return ErrInvalidBucketName
|
||||||
default:
|
default:
|
||||||
// For any other error just return AccessDenied.
|
// For any other error just return AccessDenied.
|
||||||
return false, AccessDenied
|
return ErrAccessDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Parse the saved policy.
|
// Parse the saved policy.
|
||||||
accessPolicy, e := accesspolicy.Validate(policy)
|
accessPolicy, e := accesspolicy.Validate(policy)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
errorIf(probe.NewError(e), "Parse policy failed.", nil)
|
errorIf(probe.NewError(e), "Parse policy failed.", nil)
|
||||||
return false, AccessDenied
|
return ErrAccessDenied
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct resource in 'arn:aws:s3:::examplebucket' format.
|
// Construct resource in 'arn:aws:s3:::examplebucket' format.
|
||||||
@ -71,9 +71,9 @@ func enforceBucketPolicy(action string, bucket string, reqURL *url.URL) (isAllow
|
|||||||
|
|
||||||
// Validate action, resource and conditions with current policy statements.
|
// Validate action, resource and conditions with current policy statements.
|
||||||
if !bucketPolicyEvalStatements(action, resource, conditions, accessPolicy.Statements) {
|
if !bucketPolicyEvalStatements(action, resource, conditions, accessPolicy.Statements) {
|
||||||
return false, AccessDenied
|
return ErrAccessDenied
|
||||||
}
|
}
|
||||||
return true, None
|
return ErrNone
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBucketLocationHandler - GET Bucket location.
|
// GetBucketLocationHandler - GET Bucket location.
|
||||||
@ -86,17 +86,16 @@ func (api storageAPI) GetBucketLocationHandler(w http.ResponseWriter, r *http.Re
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:GetBucketLocation", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:GetBucketLocation", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypeSigned, authTypePresigned:
|
case authTypeSigned, authTypePresigned:
|
||||||
match, s3Error := isSignV4ReqAuthenticated(api.Signature, r)
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
if !match {
|
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -107,11 +106,11 @@ func (api storageAPI) GetBucketLocationHandler(w http.ResponseWriter, r *http.Re
|
|||||||
errorIf(err.Trace(), "GetBucketMetadata failed.", nil)
|
errorIf(err.Trace(), "GetBucketMetadata failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -142,17 +141,16 @@ func (api storageAPI) ListMultipartUploadsHandler(w http.ResponseWriter, r *http
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:ListBucketMultipartUploads", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:ListBucketMultipartUploads", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypePresigned, authTypeSigned:
|
case authTypePresigned, authTypeSigned:
|
||||||
match, s3Error := isSignV4ReqAuthenticated(api.Signature, r)
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
if !match {
|
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -160,7 +158,7 @@ func (api storageAPI) ListMultipartUploadsHandler(w http.ResponseWriter, r *http
|
|||||||
|
|
||||||
resources := getBucketMultipartResources(r.URL.Query())
|
resources := getBucketMultipartResources(r.URL.Query())
|
||||||
if resources.MaxUploads < 0 {
|
if resources.MaxUploads < 0 {
|
||||||
writeErrorResponse(w, r, InvalidMaxUploads, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidMaxUploads, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if resources.MaxUploads == 0 {
|
if resources.MaxUploads == 0 {
|
||||||
@ -172,9 +170,9 @@ func (api storageAPI) ListMultipartUploadsHandler(w http.ResponseWriter, r *http
|
|||||||
errorIf(err.Trace(), "ListMultipartUploads failed.", nil)
|
errorIf(err.Trace(), "ListMultipartUploads failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -200,17 +198,16 @@ func (api storageAPI) ListObjectsHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:ListBucket", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:ListBucket", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypeSigned, authTypePresigned:
|
case authTypeSigned, authTypePresigned:
|
||||||
match, s3Error := isSignV4ReqAuthenticated(api.Signature, r)
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
if !match {
|
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -219,7 +216,7 @@ func (api storageAPI) ListObjectsHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
// TODO handle encoding type.
|
// TODO handle encoding type.
|
||||||
prefix, marker, delimiter, maxkeys, _ := getBucketResources(r.URL.Query())
|
prefix, marker, delimiter, maxkeys, _ := getBucketResources(r.URL.Query())
|
||||||
if maxkeys < 0 {
|
if maxkeys < 0 {
|
||||||
writeErrorResponse(w, r, InvalidMaxKeys, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidMaxKeys, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if maxkeys == 0 {
|
if maxkeys == 0 {
|
||||||
@ -239,16 +236,16 @@ func (api storageAPI) ListObjectsHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.ObjectNotFound:
|
case fs.ObjectNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.ObjectNameInvalid:
|
case fs.ObjectNameInvalid:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
errorIf(err.Trace(), "ListObjects failed.", nil)
|
errorIf(err.Trace(), "ListObjects failed.", nil)
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,10 +258,10 @@ func (api storageAPI) ListBucketsHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeSigned, authTypePresigned:
|
case authTypeSigned, authTypePresigned:
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -282,7 +279,7 @@ func (api storageAPI) ListBucketsHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
errorIf(err.Trace(), "ListBuckets failed.", nil)
|
errorIf(err.Trace(), "ListBuckets failed.", nil)
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteMultipleObjectsHandler - deletes multiple objects.
|
// DeleteMultipleObjectsHandler - deletes multiple objects.
|
||||||
@ -293,14 +290,14 @@ func (api storageAPI) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *htt
|
|||||||
// Content-Length is required and should be non-zero
|
// Content-Length is required and should be non-zero
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
|
||||||
if r.ContentLength <= 0 {
|
if r.ContentLength <= 0 {
|
||||||
writeErrorResponse(w, r, MissingContentLength, r.URL.Path)
|
writeErrorResponse(w, r, ErrMissingContentLength, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content-Md5 is requied should be set
|
// Content-Md5 is requied should be set
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
|
||||||
if _, ok := r.Header["Content-Md5"]; !ok {
|
if _, ok := r.Header["Content-Md5"]; !ok {
|
||||||
writeErrorResponse(w, r, MissingContentMD5, r.URL.Path)
|
writeErrorResponse(w, r, ErrMissingContentMD5, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,18 +311,18 @@ func (api storageAPI) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *htt
|
|||||||
_, e := io.ReadFull(r.Body, deleteXMLBytes)
|
_, e := io.ReadFull(r.Body, deleteXMLBytes)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
errorIf(probe.NewError(e), "DeleteMultipleObjects failed.", nil)
|
errorIf(probe.NewError(e), "DeleteMultipleObjects failed.", nil)
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:DeleteObject", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:DeleteObject", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -334,11 +331,11 @@ func (api storageAPI) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *htt
|
|||||||
ok, err := auth.DoesPresignedSignatureMatch()
|
ok, err := auth.DoesPresignedSignatureMatch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypeSigned:
|
case authTypeSigned:
|
||||||
@ -350,16 +347,16 @@ func (api storageAPI) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *htt
|
|||||||
ok, err := auth.DoesSignatureMatch(hex.EncodeToString(sha.Sum(nil)))
|
ok, err := auth.DoesSignatureMatch(hex.EncodeToString(sha.Sum(nil)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "DeleteMultipleObjects failed.", nil)
|
errorIf(err.Trace(), "DeleteMultipleObjects failed.", nil)
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Verify content md5.
|
// Verify content md5.
|
||||||
if r.Header.Get("Content-Md5") != base64.StdEncoding.EncodeToString(mdSh.Sum(nil)) {
|
if r.Header.Get("Content-Md5") != base64.StdEncoding.EncodeToString(mdSh.Sum(nil)) {
|
||||||
writeErrorResponse(w, r, BadDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrBadDigest, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,7 +364,7 @@ func (api storageAPI) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *htt
|
|||||||
// Unmarshal list of keys to be deleted.
|
// Unmarshal list of keys to be deleted.
|
||||||
deleteObjects := &DeleteObjectsRequest{}
|
deleteObjects := &DeleteObjectsRequest{}
|
||||||
if e := xml.Unmarshal(deleteXMLBytes, deleteObjects); e != nil {
|
if e := xml.Unmarshal(deleteXMLBytes, deleteObjects); e != nil {
|
||||||
writeErrorResponse(w, r, MalformedXML, r.URL.Path)
|
writeErrorResponse(w, r, ErrMalformedXML, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,32 +382,32 @@ func (api storageAPI) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *htt
|
|||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
deleteErrors = append(deleteErrors, DeleteError{
|
deleteErrors = append(deleteErrors, DeleteError{
|
||||||
Code: errorCodeResponse[InvalidBucketName].Code,
|
Code: errorCodeResponse[ErrInvalidBucketName].Code,
|
||||||
Message: errorCodeResponse[InvalidBucketName].Description,
|
Message: errorCodeResponse[ErrInvalidBucketName].Description,
|
||||||
Key: object.ObjectName,
|
Key: object.ObjectName,
|
||||||
})
|
})
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
deleteErrors = append(deleteErrors, DeleteError{
|
deleteErrors = append(deleteErrors, DeleteError{
|
||||||
Code: errorCodeResponse[NoSuchBucket].Code,
|
Code: errorCodeResponse[ErrNoSuchBucket].Code,
|
||||||
Message: errorCodeResponse[NoSuchBucket].Description,
|
Message: errorCodeResponse[ErrNoSuchBucket].Description,
|
||||||
Key: object.ObjectName,
|
Key: object.ObjectName,
|
||||||
})
|
})
|
||||||
case fs.ObjectNotFound:
|
case fs.ObjectNotFound:
|
||||||
deleteErrors = append(deleteErrors, DeleteError{
|
deleteErrors = append(deleteErrors, DeleteError{
|
||||||
Code: errorCodeResponse[NoSuchKey].Code,
|
Code: errorCodeResponse[ErrNoSuchKey].Code,
|
||||||
Message: errorCodeResponse[NoSuchKey].Description,
|
Message: errorCodeResponse[ErrNoSuchKey].Description,
|
||||||
Key: object.ObjectName,
|
Key: object.ObjectName,
|
||||||
})
|
})
|
||||||
case fs.ObjectNameInvalid:
|
case fs.ObjectNameInvalid:
|
||||||
deleteErrors = append(deleteErrors, DeleteError{
|
deleteErrors = append(deleteErrors, DeleteError{
|
||||||
Code: errorCodeResponse[NoSuchKey].Code,
|
Code: errorCodeResponse[ErrNoSuchKey].Code,
|
||||||
Message: errorCodeResponse[NoSuchKey].Description,
|
Message: errorCodeResponse[ErrNoSuchKey].Description,
|
||||||
Key: object.ObjectName,
|
Key: object.ObjectName,
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
deleteErrors = append(deleteErrors, DeleteError{
|
deleteErrors = append(deleteErrors, DeleteError{
|
||||||
Code: errorCodeResponse[InternalError].Code,
|
Code: errorCodeResponse[ErrInternalError].Code,
|
||||||
Message: errorCodeResponse[InternalError].Description,
|
Message: errorCodeResponse[ErrInternalError].Description,
|
||||||
Key: object.ObjectName,
|
Key: object.ObjectName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -437,11 +434,11 @@ func (api storageAPI) PutBucketHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:CreateBucket", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:CreateBucket", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -449,11 +446,11 @@ func (api storageAPI) PutBucketHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
ok, err := auth.DoesPresignedSignatureMatch()
|
ok, err := auth.DoesPresignedSignatureMatch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypeSigned:
|
case authTypeSigned:
|
||||||
@ -461,7 +458,7 @@ func (api storageAPI) PutBucketHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
locationBytes, e := ioutil.ReadAll(r.Body)
|
locationBytes, e := ioutil.ReadAll(r.Body)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
errorIf(probe.NewError(e), "MakeBucket failed.", nil)
|
errorIf(probe.NewError(e), "MakeBucket failed.", nil)
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sh := sha256.New()
|
sh := sha256.New()
|
||||||
@ -469,11 +466,11 @@ func (api storageAPI) PutBucketHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
ok, err := auth.DoesSignatureMatch(hex.EncodeToString(sh.Sum(nil)))
|
ok, err := auth.DoesSignatureMatch(hex.EncodeToString(sh.Sum(nil)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "MakeBucket failed.", nil)
|
errorIf(err.Trace(), "MakeBucket failed.", nil)
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -484,11 +481,11 @@ func (api storageAPI) PutBucketHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
errorIf(err.Trace(), "MakeBucket failed.", nil)
|
errorIf(err.Trace(), "MakeBucket failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketExists:
|
case fs.BucketExists:
|
||||||
writeErrorResponse(w, r, BucketAlreadyExists, r.URL.Path)
|
writeErrorResponse(w, r, ErrBucketAlreadyExists, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -527,29 +524,20 @@ func extractHTTPFormValues(reader *multipart.Reader) (io.Reader, map[string]stri
|
|||||||
// This implementation of the POST operation handles object creation with a specified
|
// This implementation of the POST operation handles object creation with a specified
|
||||||
// signature policy in multipart/form-data
|
// signature policy in multipart/form-data
|
||||||
func (api storageAPI) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Request) {
|
func (api storageAPI) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
// if body of request is non-nil then check for validity of Content-Length
|
|
||||||
if r.Body != nil {
|
|
||||||
/// if Content-Length is unknown/missing, deny the request
|
|
||||||
if r.ContentLength == -1 {
|
|
||||||
writeErrorResponse(w, r, MissingContentLength, r.URL.Path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Here the parameter is the size of the form data that should
|
// Here the parameter is the size of the form data that should
|
||||||
// be loaded in memory, the remaining being put in temporary
|
// be loaded in memory, the remaining being put in temporary
|
||||||
// files
|
// files
|
||||||
reader, e := r.MultipartReader()
|
reader, e := r.MultipartReader()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
errorIf(probe.NewError(e), "Unable to initialize multipart reader.", nil)
|
errorIf(probe.NewError(e), "Unable to initialize multipart reader.", nil)
|
||||||
writeErrorResponse(w, r, MalformedPOSTRequest, r.URL.Path)
|
writeErrorResponse(w, r, ErrMalformedPOSTRequest, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fileBody, formValues, err := extractHTTPFormValues(reader)
|
fileBody, formValues, err := extractHTTPFormValues(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "Unable to parse form values.", nil)
|
errorIf(err.Trace(), "Unable to parse form values.", nil)
|
||||||
writeErrorResponse(w, r, MalformedPOSTRequest, r.URL.Path)
|
writeErrorResponse(w, r, ErrMalformedPOSTRequest, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bucket := mux.Vars(r)["bucket"]
|
bucket := mux.Vars(r)["bucket"]
|
||||||
@ -564,16 +552,16 @@ func (api storageAPI) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Req
|
|||||||
ok, err = auth.DoesPolicySignatureMatch(formValues)
|
ok, err = auth.DoesPolicySignatureMatch(formValues)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(), "Unable to verify signature.", nil)
|
errorIf(err.Trace(), "Unable to verify signature.", nil)
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = signature4.ApplyPolicyCond(formValues); err != nil {
|
if err = signature4.ApplyPolicyCond(formValues); err != nil {
|
||||||
errorIf(err.Trace(), "Invalid request, policy doesn't match with the endpoint.", nil)
|
errorIf(err.Trace(), "Invalid request, policy doesn't match with the endpoint.", nil)
|
||||||
writeErrorResponse(w, r, MalformedPOSTRequest, r.URL.Path)
|
writeErrorResponse(w, r, ErrMalformedPOSTRequest, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
metadata, err := api.Filesystem.CreateObject(bucket, object, "", -1, fileBody, nil)
|
metadata, err := api.Filesystem.CreateObject(bucket, object, "", -1, fileBody, nil)
|
||||||
@ -581,19 +569,19 @@ func (api storageAPI) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Req
|
|||||||
errorIf(err.Trace(), "CreateObject failed.", nil)
|
errorIf(err.Trace(), "CreateObject failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.RootPathFull:
|
case fs.RootPathFull:
|
||||||
writeErrorResponse(w, r, RootPathFull, r.URL.Path)
|
writeErrorResponse(w, r, ErrRootPathFull, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BadDigest:
|
case fs.BadDigest:
|
||||||
writeErrorResponse(w, r, BadDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrBadDigest, r.URL.Path)
|
||||||
case fs.IncompleteBody:
|
case fs.IncompleteBody:
|
||||||
writeErrorResponse(w, r, IncompleteBody, r.URL.Path)
|
writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path)
|
||||||
case fs.InvalidDigest:
|
case fs.InvalidDigest:
|
||||||
writeErrorResponse(w, r, InvalidDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidDigest, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -616,10 +604,10 @@ func (api storageAPI) HeadBucketHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypePresigned, authTypeSigned:
|
case authTypePresigned, authTypeSigned:
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -630,11 +618,11 @@ func (api storageAPI) HeadBucketHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
errorIf(err.Trace(), "GetBucketMetadata failed.", nil)
|
errorIf(err.Trace(), "GetBucketMetadata failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -649,16 +637,16 @@ func (api storageAPI) DeleteBucketHandler(w http.ResponseWriter, r *http.Request
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:DeleteBucket", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:DeleteBucket", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypePresigned, authTypeSigned:
|
case authTypePresigned, authTypeSigned:
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -669,11 +657,11 @@ func (api storageAPI) DeleteBucketHandler(w http.ResponseWriter, r *http.Request
|
|||||||
errorIf(err.Trace(), "DeleteBucket failed.", nil)
|
errorIf(err.Trace(), "DeleteBucket failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.BucketNotEmpty:
|
case fs.BucketNotEmpty:
|
||||||
writeErrorResponse(w, r, BucketNotEmpty, r.URL.Path)
|
writeErrorResponse(w, r, ErrBucketNotEmpty, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -139,12 +139,12 @@ func (api storageAPI) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
// incoming request is not chunked.
|
// incoming request is not chunked.
|
||||||
if !contains(r.TransferEncoding, "chunked") {
|
if !contains(r.TransferEncoding, "chunked") {
|
||||||
if r.ContentLength == -1 || r.ContentLength == 0 {
|
if r.ContentLength == -1 || r.ContentLength == 0 {
|
||||||
writeErrorResponse(w, r, MissingContentLength, r.URL.Path)
|
writeErrorResponse(w, r, ErrMissingContentLength, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// If Content-Length is greater than maximum allowed policy size.
|
// If Content-Length is greater than maximum allowed policy size.
|
||||||
if r.ContentLength > maxAccessPolicySize {
|
if r.ContentLength > maxAccessPolicySize {
|
||||||
writeErrorResponse(w, r, EntityTooLarge, r.URL.Path)
|
writeErrorResponse(w, r, ErrEntityTooLarge, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -155,14 +155,14 @@ func (api storageAPI) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
accessPolicyBytes, e := ioutil.ReadAll(io.LimitReader(r.Body, maxAccessPolicySize))
|
accessPolicyBytes, e := ioutil.ReadAll(io.LimitReader(r.Body, maxAccessPolicySize))
|
||||||
if e != nil {
|
if e != nil {
|
||||||
errorIf(probe.NewError(e).Trace(bucket), "Reading policy failed.", nil)
|
errorIf(probe.NewError(e).Trace(bucket), "Reading policy failed.", nil)
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse access access.
|
// Parse access access.
|
||||||
accessPolicy, e := accesspolicy.Validate(accessPolicyBytes)
|
accessPolicy, e := accesspolicy.Validate(accessPolicyBytes)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
writeErrorResponse(w, r, InvalidPolicyDocument, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidPolicyDocument, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ func (api storageAPI) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
for _, resource := range statement.Resources {
|
for _, resource := range statement.Resources {
|
||||||
resourcePrefix := strings.SplitAfter(resource, accesspolicy.AWSResourcePrefix)[1]
|
resourcePrefix := strings.SplitAfter(resource, accesspolicy.AWSResourcePrefix)[1]
|
||||||
if !strings.HasPrefix(resourcePrefix, bucket) {
|
if !strings.HasPrefix(resourcePrefix, bucket) {
|
||||||
writeErrorResponse(w, r, MalformedPolicy, r.URL.Path)
|
writeErrorResponse(w, r, ErrMalformedPolicy, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,11 +183,11 @@ func (api storageAPI) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
ok, err := auth.DoesPresignedSignatureMatch()
|
ok, err := auth.DoesPresignedSignatureMatch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if isRequestSignatureV4(r) {
|
} else if isRequestSignatureV4(r) {
|
||||||
@ -196,11 +196,11 @@ func (api storageAPI) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
ok, err := api.Signature.DoesSignatureMatch(hex.EncodeToString(sh.Sum(nil)))
|
ok, err := api.Signature.DoesSignatureMatch(hex.EncodeToString(sh.Sum(nil)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(string(accessPolicyBytes)), "SaveBucketPolicy failed.", nil)
|
errorIf(err.Trace(string(accessPolicyBytes)), "SaveBucketPolicy failed.", nil)
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,9 +211,9 @@ func (api storageAPI) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
errorIf(err.Trace(bucket), "SaveBucketPolicy failed.", nil)
|
errorIf(err.Trace(bucket), "SaveBucketPolicy failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -229,7 +229,7 @@ func (api storageAPI) DeleteBucketPolicyHandler(w http.ResponseWriter, r *http.R
|
|||||||
bucket := vars["bucket"]
|
bucket := vars["bucket"]
|
||||||
|
|
||||||
// Validate incoming signature.
|
// Validate incoming signature.
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -240,11 +240,11 @@ func (api storageAPI) DeleteBucketPolicyHandler(w http.ResponseWriter, r *http.R
|
|||||||
errorIf(err.Trace(bucket), "DeleteBucketPolicy failed.", nil)
|
errorIf(err.Trace(bucket), "DeleteBucketPolicy failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketPolicyNotFound:
|
case fs.BucketPolicyNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucketPolicy, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucketPolicy, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -260,7 +260,7 @@ func (api storageAPI) GetBucketPolicyHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
bucket := vars["bucket"]
|
bucket := vars["bucket"]
|
||||||
|
|
||||||
// Validate incoming signature.
|
// Validate incoming signature.
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -271,11 +271,11 @@ func (api storageAPI) GetBucketPolicyHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
errorIf(err.Trace(bucket), "GetBucketPolicy failed.", nil)
|
errorIf(err.Trace(bucket), "GetBucketPolicy failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketPolicyNotFound:
|
case fs.BucketPolicyNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucketPolicy, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucketPolicy, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ func (h cacheControlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
// For all browser requests set appropriate Cache-Control policies
|
// For all browser requests set appropriate Cache-Control policies
|
||||||
match, e := regexp.MatchString(privateBucket+`/([^/]+\.js|favicon.ico)`, r.URL.Path)
|
match, e := regexp.MatchString(privateBucket+`/([^/]+\.js|favicon.ico)`, r.URL.Path)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if match {
|
if match {
|
||||||
@ -114,7 +114,7 @@ func setPrivateBucketHandler(h http.Handler) http.Handler {
|
|||||||
func (h minioPrivateBucketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h minioPrivateBucketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// For all non browser requests, reject access to 'privateBucket'.
|
// For all non browser requests, reject access to 'privateBucket'.
|
||||||
if !strings.Contains(r.Header.Get("User-Agent"), "Mozilla") && path.Clean(r.URL.Path) == privateBucket {
|
if !strings.Contains(r.Header.Get("User-Agent"), "Mozilla") && path.Clean(r.URL.Path) == privateBucket {
|
||||||
writeErrorResponse(w, r, AllAccessDisabled, r.URL.Path)
|
writeErrorResponse(w, r, ErrAllAccessDisabled, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.handler.ServeHTTP(w, r)
|
h.handler.ServeHTTP(w, r)
|
||||||
@ -184,13 +184,13 @@ func (h timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
// All our internal APIs are sensitive towards Date
|
// All our internal APIs are sensitive towards Date
|
||||||
// header, for all requests where Date header is not
|
// header, for all requests where Date header is not
|
||||||
// present we will reject such clients.
|
// present we will reject such clients.
|
||||||
writeErrorResponse(w, r, RequestTimeTooSkewed, r.URL.Path)
|
writeErrorResponse(w, r, ErrRequestTimeTooSkewed, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Verify if the request date header is more than 5minutes
|
// Verify if the request date header is more than 5minutes
|
||||||
// late, reject such clients.
|
// late, reject such clients.
|
||||||
if time.Now().UTC().Sub(date)/time.Minute > time.Duration(5)*time.Minute {
|
if time.Now().UTC().Sub(date)/time.Minute > time.Duration(5)*time.Minute {
|
||||||
writeErrorResponse(w, r, RequestTimeTooSkewed, r.URL.Path)
|
writeErrorResponse(w, r, ErrRequestTimeTooSkewed, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,20 +237,20 @@ func (h resourceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
// level resource queries.
|
// level resource queries.
|
||||||
if bucketName != "" && objectName == "" {
|
if bucketName != "" && objectName == "" {
|
||||||
if ignoreNotImplementedBucketResources(r) {
|
if ignoreNotImplementedBucketResources(r) {
|
||||||
writeErrorResponse(w, r, NotImplemented, r.URL.Path)
|
writeErrorResponse(w, r, ErrNotImplemented, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If bucketName and objectName are present check for its resource queries.
|
// If bucketName and objectName are present check for its resource queries.
|
||||||
if bucketName != "" && objectName != "" {
|
if bucketName != "" && objectName != "" {
|
||||||
if ignoreNotImplementedObjectResources(r) {
|
if ignoreNotImplementedObjectResources(r) {
|
||||||
writeErrorResponse(w, r, NotImplemented, r.URL.Path)
|
writeErrorResponse(w, r, ErrNotImplemented, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// A put method on path "/" doesn't make sense, ignore it.
|
// A put method on path "/" doesn't make sense, ignore it.
|
||||||
if r.Method == "PUT" && r.URL.Path == "/" {
|
if r.Method == "PUT" && r.URL.Path == "/" {
|
||||||
writeErrorResponse(w, r, NotImplemented, r.URL.Path)
|
writeErrorResponse(w, r, ErrNotImplemented, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.handler.ServeHTTP(w, r)
|
h.handler.ServeHTTP(w, r)
|
||||||
|
@ -64,16 +64,16 @@ func (api storageAPI) GetObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:GetObject", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:GetObject", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypePresigned, authTypeSigned:
|
case authTypePresigned, authTypeSigned:
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -84,15 +84,15 @@ func (api storageAPI) GetObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
errorIf(err.Trace(), "GetObject failed.", nil)
|
errorIf(err.Trace(), "GetObject failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.ObjectNotFound:
|
case fs.ObjectNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.ObjectNameInvalid:
|
case fs.ObjectNameInvalid:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ func (api storageAPI) GetObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
var hrange *httpRange
|
var hrange *httpRange
|
||||||
hrange, err = getRequestedRange(r.Header.Get("Range"), metadata.Size)
|
hrange, err = getRequestedRange(r.Header.Get("Range"), metadata.Size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(w, r, InvalidRange, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidRange, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ func (api storageAPI) HeadObjectHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
bucket = vars["bucket"]
|
bucket = vars["bucket"]
|
||||||
object = vars["object"]
|
object = vars["object"]
|
||||||
|
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -240,15 +240,15 @@ func (api storageAPI) HeadObjectHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.ObjectNotFound:
|
case fs.ObjectNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.ObjectNameInvalid:
|
case fs.ObjectNameInvalid:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -288,16 +288,16 @@ func (api storageAPI) CopyObjectHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:GetBucketLocation", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:GetBucketLocation", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypePresigned, authTypeSigned:
|
case authTypePresigned, authTypeSigned:
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -323,13 +323,13 @@ func (api storageAPI) CopyObjectHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
// If source object is empty, reply back error.
|
// If source object is empty, reply back error.
|
||||||
if sourceObject == "" {
|
if sourceObject == "" {
|
||||||
writeErrorResponse(w, r, InvalidCopySource, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidCopySource, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Source and destination objects cannot be same, reply back error.
|
// Source and destination objects cannot be same, reply back error.
|
||||||
if sourceObject == object && sourceBucket == bucket {
|
if sourceObject == object && sourceBucket == bucket {
|
||||||
writeErrorResponse(w, r, InvalidCopyDest, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidCopyDest, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,22 +338,22 @@ func (api storageAPI) CopyObjectHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
errorIf(err.Trace(), "GetObjectMetadata failed.", nil)
|
errorIf(err.Trace(), "GetObjectMetadata failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, objectSource)
|
writeErrorResponse(w, r, ErrInvalidBucketName, objectSource)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, objectSource)
|
writeErrorResponse(w, r, ErrNoSuchBucket, objectSource)
|
||||||
case fs.ObjectNotFound:
|
case fs.ObjectNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchKey, objectSource)
|
writeErrorResponse(w, r, ErrNoSuchKey, objectSource)
|
||||||
case fs.ObjectNameInvalid:
|
case fs.ObjectNameInvalid:
|
||||||
writeErrorResponse(w, r, NoSuchKey, objectSource)
|
writeErrorResponse(w, r, ErrNoSuchKey, objectSource)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, objectSource)
|
writeErrorResponse(w, r, ErrInternalError, objectSource)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/// maximum Upload size for object in a single CopyObject operation.
|
/// maximum Upload size for object in a single CopyObject operation.
|
||||||
if isMaxObjectSize(metadata.Size) {
|
if isMaxObjectSize(metadata.Size) {
|
||||||
writeErrorResponse(w, r, EntityTooLarge, objectSource)
|
writeErrorResponse(w, r, ErrEntityTooLarge, objectSource)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,21 +380,21 @@ func (api storageAPI) CopyObjectHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
errorIf(err.Trace(), "CreateObject failed.", nil)
|
errorIf(err.Trace(), "CreateObject failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.RootPathFull:
|
case fs.RootPathFull:
|
||||||
writeErrorResponse(w, r, RootPathFull, r.URL.Path)
|
writeErrorResponse(w, r, ErrRootPathFull, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BadDigest:
|
case fs.BadDigest:
|
||||||
writeErrorResponse(w, r, BadDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrBadDigest, r.URL.Path)
|
||||||
case fs.IncompleteBody:
|
case fs.IncompleteBody:
|
||||||
writeErrorResponse(w, r, IncompleteBody, r.URL.Path)
|
writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path)
|
||||||
case fs.InvalidDigest:
|
case fs.InvalidDigest:
|
||||||
writeErrorResponse(w, r, InvalidDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidDigest, r.URL.Path)
|
||||||
case fs.ObjectExistsAsPrefix:
|
case fs.ObjectExistsAsPrefix:
|
||||||
writeErrorResponse(w, r, ObjectExistsAsPrefix, r.URL.Path)
|
writeErrorResponse(w, r, ErrObjectExistsAsPrefix, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -413,7 +413,7 @@ func (api storageAPI) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
// If the matching failed, it means that the X-Amz-Copy-Source was
|
// If the matching failed, it means that the X-Amz-Copy-Source was
|
||||||
// wrong, fail right here.
|
// wrong, fail right here.
|
||||||
if _, ok := r.Header["X-Amz-Copy-Source"]; ok {
|
if _, ok := r.Header["X-Amz-Copy-Source"]; ok {
|
||||||
writeErrorResponse(w, r, InvalidCopySource, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidCopySource, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
@ -423,18 +423,18 @@ func (api storageAPI) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
// get Content-Md5 sent by client and verify if valid
|
// get Content-Md5 sent by client and verify if valid
|
||||||
md5 := r.Header.Get("Content-Md5")
|
md5 := r.Header.Get("Content-Md5")
|
||||||
if !isValidMD5(md5) {
|
if !isValidMD5(md5) {
|
||||||
writeErrorResponse(w, r, InvalidDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidDigest, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
/// if Content-Length is unknown/missing, deny the request
|
/// if Content-Length is unknown/missing, deny the request
|
||||||
size := r.ContentLength
|
size := r.ContentLength
|
||||||
if size == -1 && !contains(r.TransferEncoding, "chunked") {
|
if size == -1 && !contains(r.TransferEncoding, "chunked") {
|
||||||
writeErrorResponse(w, r, MissingContentLength, r.URL.Path)
|
writeErrorResponse(w, r, ErrMissingContentLength, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
/// maximum Upload size for objects in a single operation
|
/// maximum Upload size for objects in a single operation
|
||||||
if isMaxObjectSize(size) {
|
if isMaxObjectSize(size) {
|
||||||
writeErrorResponse(w, r, EntityTooLarge, r.URL.Path)
|
writeErrorResponse(w, r, ErrEntityTooLarge, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,11 +445,11 @@ func (api storageAPI) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:PutObject", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:PutObject", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -461,11 +461,11 @@ func (api storageAPI) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
ok, err = auth.DoesPresignedSignatureMatch()
|
ok, err = auth.DoesPresignedSignatureMatch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Create presigned object.
|
// Create presigned object.
|
||||||
@ -478,23 +478,23 @@ func (api storageAPI) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
errorIf(err.Trace(), "CreateObject failed.", nil)
|
errorIf(err.Trace(), "CreateObject failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.RootPathFull:
|
case fs.RootPathFull:
|
||||||
writeErrorResponse(w, r, RootPathFull, r.URL.Path)
|
writeErrorResponse(w, r, ErrRootPathFull, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BadDigest:
|
case fs.BadDigest:
|
||||||
writeErrorResponse(w, r, BadDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrBadDigest, r.URL.Path)
|
||||||
case fs.SignDoesNotMatch:
|
case fs.SignDoesNotMatch:
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
case fs.IncompleteBody:
|
case fs.IncompleteBody:
|
||||||
writeErrorResponse(w, r, IncompleteBody, r.URL.Path)
|
writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path)
|
||||||
case fs.InvalidDigest:
|
case fs.InvalidDigest:
|
||||||
writeErrorResponse(w, r, InvalidDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidDigest, r.URL.Path)
|
||||||
case fs.ObjectExistsAsPrefix:
|
case fs.ObjectExistsAsPrefix:
|
||||||
writeErrorResponse(w, r, ObjectExistsAsPrefix, r.URL.Path)
|
writeErrorResponse(w, r, ErrObjectExistsAsPrefix, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -516,12 +516,12 @@ func (api storageAPI) NewMultipartUploadHandler(w http.ResponseWriter, r *http.R
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:PutObject", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:PutObject", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -532,17 +532,17 @@ func (api storageAPI) NewMultipartUploadHandler(w http.ResponseWriter, r *http.R
|
|||||||
errorIf(err.Trace(), "NewMultipartUpload failed.", nil)
|
errorIf(err.Trace(), "NewMultipartUpload failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.RootPathFull:
|
case fs.RootPathFull:
|
||||||
writeErrorResponse(w, r, RootPathFull, r.URL.Path)
|
writeErrorResponse(w, r, ErrRootPathFull, r.URL.Path)
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.ObjectNotFound:
|
case fs.ObjectNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.ObjectNameInvalid:
|
case fs.ObjectNameInvalid:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -564,20 +564,20 @@ func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Reques
|
|||||||
// get Content-Md5 sent by client and verify if valid
|
// get Content-Md5 sent by client and verify if valid
|
||||||
md5 := r.Header.Get("Content-Md5")
|
md5 := r.Header.Get("Content-Md5")
|
||||||
if !isValidMD5(md5) {
|
if !isValidMD5(md5) {
|
||||||
writeErrorResponse(w, r, InvalidDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidDigest, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/// if Content-Length is unknown/missing, throw away
|
/// if Content-Length is unknown/missing, throw away
|
||||||
size := r.ContentLength
|
size := r.ContentLength
|
||||||
if size == -1 {
|
if size == -1 {
|
||||||
writeErrorResponse(w, r, MissingContentLength, r.URL.Path)
|
writeErrorResponse(w, r, ErrMissingContentLength, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/// maximum Upload size for multipart objects in a single operation
|
/// maximum Upload size for multipart objects in a single operation
|
||||||
if isMaxObjectSize(size) {
|
if isMaxObjectSize(size) {
|
||||||
writeErrorResponse(w, r, EntityTooLarge, r.URL.Path)
|
writeErrorResponse(w, r, ErrEntityTooLarge, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,7 +586,7 @@ func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Reques
|
|||||||
|
|
||||||
partID, e := strconv.Atoi(partIDString)
|
partID, e := strconv.Atoi(partIDString)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
writeErrorResponse(w, r, InvalidPart, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidPart, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,7 +597,7 @@ func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Reques
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:PutObject", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:PutObject", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -610,11 +610,11 @@ func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Reques
|
|||||||
ok, err = auth.DoesPresignedSignatureMatch()
|
ok, err = auth.DoesPresignedSignatureMatch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
partMD5, err = api.Filesystem.CreateObjectPart(bucket, object, uploadID, md5, partID, size, r.Body, nil)
|
partMD5, err = api.Filesystem.CreateObjectPart(bucket, object, uploadID, md5, partID, size, r.Body, nil)
|
||||||
@ -625,19 +625,19 @@ func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Reques
|
|||||||
errorIf(err.Trace(), "CreateObjectPart failed.", nil)
|
errorIf(err.Trace(), "CreateObjectPart failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.RootPathFull:
|
case fs.RootPathFull:
|
||||||
writeErrorResponse(w, r, RootPathFull, r.URL.Path)
|
writeErrorResponse(w, r, ErrRootPathFull, r.URL.Path)
|
||||||
case fs.InvalidUploadID:
|
case fs.InvalidUploadID:
|
||||||
writeErrorResponse(w, r, NoSuchUpload, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path)
|
||||||
case fs.BadDigest:
|
case fs.BadDigest:
|
||||||
writeErrorResponse(w, r, BadDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrBadDigest, r.URL.Path)
|
||||||
case fs.SignDoesNotMatch:
|
case fs.SignDoesNotMatch:
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
case fs.IncompleteBody:
|
case fs.IncompleteBody:
|
||||||
writeErrorResponse(w, r, IncompleteBody, r.URL.Path)
|
writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path)
|
||||||
case fs.InvalidDigest:
|
case fs.InvalidDigest:
|
||||||
writeErrorResponse(w, r, InvalidDigest, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidDigest, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -656,12 +656,12 @@ func (api storageAPI) AbortMultipartUploadHandler(w http.ResponseWriter, r *http
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:AbortMultipartUpload", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:AbortMultipartUpload", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -673,17 +673,17 @@ func (api storageAPI) AbortMultipartUploadHandler(w http.ResponseWriter, r *http
|
|||||||
errorIf(err.Trace(), "AbortMutlipartUpload failed.", nil)
|
errorIf(err.Trace(), "AbortMutlipartUpload failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.ObjectNotFound:
|
case fs.ObjectNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.ObjectNameInvalid:
|
case fs.ObjectNameInvalid:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.InvalidUploadID:
|
case fs.InvalidUploadID:
|
||||||
writeErrorResponse(w, r, NoSuchUpload, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -699,12 +699,12 @@ func (api storageAPI) ListObjectPartsHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:ListMultipartUploadParts", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:ListMultipartUploadParts", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -712,11 +712,11 @@ func (api storageAPI) ListObjectPartsHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
|
|
||||||
objectResourcesMetadata := getObjectResources(r.URL.Query())
|
objectResourcesMetadata := getObjectResources(r.URL.Query())
|
||||||
if objectResourcesMetadata.PartNumberMarker < 0 {
|
if objectResourcesMetadata.PartNumberMarker < 0 {
|
||||||
writeErrorResponse(w, r, InvalidPartNumberMarker, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidPartNumberMarker, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if objectResourcesMetadata.MaxParts < 0 {
|
if objectResourcesMetadata.MaxParts < 0 {
|
||||||
writeErrorResponse(w, r, InvalidMaxParts, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidMaxParts, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if objectResourcesMetadata.MaxParts == 0 {
|
if objectResourcesMetadata.MaxParts == 0 {
|
||||||
@ -728,17 +728,17 @@ func (api storageAPI) ListObjectPartsHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
errorIf(err.Trace(), "ListObjectParts failed.", nil)
|
errorIf(err.Trace(), "ListObjectParts failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.ObjectNotFound:
|
case fs.ObjectNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.ObjectNameInvalid:
|
case fs.ObjectNameInvalid:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.InvalidUploadID:
|
case fs.InvalidUploadID:
|
||||||
writeErrorResponse(w, r, NoSuchUpload, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -767,11 +767,11 @@ func (api storageAPI) CompleteMultipartUploadHandler(w http.ResponseWriter, r *h
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:PutObject", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:PutObject", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -783,11 +783,11 @@ func (api storageAPI) CompleteMultipartUploadHandler(w http.ResponseWriter, r *h
|
|||||||
ok, err = auth.DoesPresignedSignatureMatch()
|
ok, err = auth.DoesPresignedSignatureMatch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Complete multipart upload presigned.
|
// Complete multipart upload presigned.
|
||||||
@ -800,27 +800,27 @@ func (api storageAPI) CompleteMultipartUploadHandler(w http.ResponseWriter, r *h
|
|||||||
errorIf(err.Trace(), "CompleteMultipartUpload failed.", nil)
|
errorIf(err.Trace(), "CompleteMultipartUpload failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.ObjectNotFound:
|
case fs.ObjectNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.ObjectNameInvalid:
|
case fs.ObjectNameInvalid:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.InvalidUploadID:
|
case fs.InvalidUploadID:
|
||||||
writeErrorResponse(w, r, NoSuchUpload, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchUpload, r.URL.Path)
|
||||||
case fs.InvalidPart:
|
case fs.InvalidPart:
|
||||||
writeErrorResponse(w, r, InvalidPart, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidPart, r.URL.Path)
|
||||||
case fs.InvalidPartOrder:
|
case fs.InvalidPartOrder:
|
||||||
writeErrorResponse(w, r, InvalidPartOrder, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidPartOrder, r.URL.Path)
|
||||||
case fs.SignDoesNotMatch:
|
case fs.SignDoesNotMatch:
|
||||||
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
|
writeErrorResponse(w, r, ErrSignatureDoesNotMatch, r.URL.Path)
|
||||||
case fs.IncompleteBody:
|
case fs.IncompleteBody:
|
||||||
writeErrorResponse(w, r, IncompleteBody, r.URL.Path)
|
writeErrorResponse(w, r, ErrIncompleteBody, r.URL.Path)
|
||||||
case fs.MalformedXML:
|
case fs.MalformedXML:
|
||||||
writeErrorResponse(w, r, MalformedXML, r.URL.Path)
|
writeErrorResponse(w, r, ErrMalformedXML, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -846,16 +846,16 @@ func (api storageAPI) DeleteObjectHandler(w http.ResponseWriter, r *http.Request
|
|||||||
switch getRequestAuthType(r) {
|
switch getRequestAuthType(r) {
|
||||||
default:
|
default:
|
||||||
// For all unknown auth types return error.
|
// For all unknown auth types return error.
|
||||||
writeErrorResponse(w, r, AccessDenied, r.URL.Path)
|
writeErrorResponse(w, r, ErrAccessDenied, r.URL.Path)
|
||||||
return
|
return
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html
|
||||||
if isAllowed, s3Error := enforceBucketPolicy("s3:DeleteObject", bucket, r.URL); !isAllowed {
|
if s3Error := enforceBucketPolicy("s3:DeleteObject", bucket, r.URL); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case authTypeSigned, authTypePresigned:
|
case authTypeSigned, authTypePresigned:
|
||||||
if match, s3Error := isSignV4ReqAuthenticated(api.Signature, r); !match {
|
if s3Error := isReqAuthenticated(api.Signature, r); s3Error != ErrNone {
|
||||||
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
writeErrorResponse(w, r, s3Error, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -865,15 +865,15 @@ func (api storageAPI) DeleteObjectHandler(w http.ResponseWriter, r *http.Request
|
|||||||
errorIf(err.Trace(), "DeleteObject failed.", nil)
|
errorIf(err.Trace(), "DeleteObject failed.", nil)
|
||||||
switch err.ToGoError().(type) {
|
switch err.ToGoError().(type) {
|
||||||
case fs.BucketNameInvalid:
|
case fs.BucketNameInvalid:
|
||||||
writeErrorResponse(w, r, InvalidBucketName, r.URL.Path)
|
writeErrorResponse(w, r, ErrInvalidBucketName, r.URL.Path)
|
||||||
case fs.BucketNotFound:
|
case fs.BucketNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchBucket, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchBucket, r.URL.Path)
|
||||||
case fs.ObjectNotFound:
|
case fs.ObjectNotFound:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
case fs.ObjectNameInvalid:
|
case fs.ObjectNameInvalid:
|
||||||
writeErrorResponse(w, r, NoSuchKey, r.URL.Path)
|
writeErrorResponse(w, r, ErrNoSuchKey, r.URL.Path)
|
||||||
default:
|
default:
|
||||||
writeErrorResponse(w, r, InternalError, r.URL.Path)
|
writeErrorResponse(w, r, ErrInternalError, r.URL.Path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeSuccessNoContent(w)
|
writeSuccessNoContent(w)
|
||||||
|
@ -40,7 +40,7 @@ func TestListBuckets(t *testing.T) {
|
|||||||
|
|
||||||
// Create a few buckets.
|
// Create a few buckets.
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
err = filesystem.MakeBucket("testbucket."+strconv.Itoa(i), "public-read")
|
err = filesystem.MakeBucket("testbucket." + strconv.Itoa(i))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ func TestListBuckets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(metadatas) != 10 {
|
if len(metadatas) != 10 {
|
||||||
t.Errorf("incorrect length of metadatas (%i)\n", len(metadatas))
|
t.Errorf("incorrect length of metadatas (%d)\n", len(metadatas))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over the buckets, ensuring that the name is correct.
|
// Iterate over the buckets, ensuring that the name is correct.
|
||||||
@ -101,7 +101,7 @@ func BenchmarkListBuckets(b *testing.B) {
|
|||||||
|
|
||||||
// Create a few buckets.
|
// Create a few buckets.
|
||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
err = filesystem.MakeBucket("bucket."+strconv.Itoa(i), "public-read")
|
err = filesystem.MakeBucket("bucket." + strconv.Itoa(i))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user