Support unknown gateway errors and convert at handler layer (#7219)

Different gateway implementations due to different backend
API errors, might return different unsupported errors at
our handler layer. Current code posed a problem for us because
this information was lost and we would convert it to InternalError
in this situation all S3 clients end up retrying the request.

To avoid this unexpected situation implement a way to support
this cleanly such that the underlying information is not lost
which is returned by gateway.
This commit is contained in:
Harshavardhana 2019-02-12 01:25:52 -08:00 committed by Nitish Tiwari
parent 9f87283cd5
commit fef5416b3c
29 changed files with 677 additions and 779 deletions

View File

@ -64,21 +64,21 @@ func (api objectAPIHandlers) GetBucketACLHandler(w http.ResponseWriter, r *http.
objAPI := api.ObjectAPI() objAPI := api.ObjectAPI()
if objAPI == nil { if objAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
// Allow getBucketACL if policy action is set, since this is a dummy call // Allow getBucketACL if policy action is set, since this is a dummy call
// we are simply re-purposing the bucketPolicyAction. // we are simply re-purposing the bucketPolicyAction.
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Before proceeding validate if bucket exists. // Before proceeding validate if bucket exists.
_, err := objAPI.GetBucketInfo(ctx, bucket) _, err := objAPI.GetBucketInfo(ctx, bucket)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -92,7 +92,7 @@ func (api objectAPIHandlers) GetBucketACLHandler(w http.ResponseWriter, r *http.
Permission: "FULL_CONTROL", Permission: "FULL_CONTROL",
}) })
if err := xml.NewEncoder(w).Encode(acl); err != nil { if err := xml.NewEncoder(w).Encode(acl); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -114,21 +114,21 @@ func (api objectAPIHandlers) GetObjectACLHandler(w http.ResponseWriter, r *http.
objAPI := api.ObjectAPI() objAPI := api.ObjectAPI()
if objAPI == nil { if objAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
// Allow getObjectACL if policy action is set, since this is a dummy call // Allow getObjectACL if policy action is set, since this is a dummy call
// we are simply re-purposing the bucketPolicyAction. // we are simply re-purposing the bucketPolicyAction.
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Before proceeding validate if object exists. // Before proceeding validate if object exists.
_, err := objAPI.GetObjectInfo(ctx, bucket, object, ObjectOptions{}) _, err := objAPI.GetObjectInfo(ctx, bucket, object, ObjectOptions{})
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -142,7 +142,7 @@ func (api objectAPIHandlers) GetObjectACLHandler(w http.ResponseWriter, r *http.
Permission: "FULL_CONTROL", Permission: "FULL_CONTROL",
}) })
if err := xml.NewEncoder(w).Encode(acl); err != nil { if err := xml.NewEncoder(w).Encode(acl); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }

File diff suppressed because it is too large Load Diff

View File

@ -270,10 +270,16 @@ func prepareAdminXLTestBed() (*adminXLTestBed, error) {
// Init global heal state // Init global heal state
initAllHealState(globalIsXL) initAllHealState(globalIsXL)
globalNotificationSys = NewNotificationSys(globalServerConfig, globalEndpoints) globalConfigSys = NewConfigSys()
globalIAMSys = NewIAMSys()
globalIAMSys.Init(objLayer)
// Create new policy system.
globalPolicySys = NewPolicySys() globalPolicySys = NewPolicySys()
globalPolicySys.Init(objLayer)
globalNotificationSys = NewNotificationSys(globalServerConfig, globalEndpoints)
globalNotificationSys.Init(objLayer)
// Setup admin mgmt REST API handlers. // Setup admin mgmt REST API handlers.
adminRouter := mux.NewRouter() adminRouter := mux.NewRouter()
@ -842,8 +848,8 @@ func TestAdminServerInfo(t *testing.T) {
} }
} }
// TestToAdminAPIErr - test for toAdminAPIErr helper function. // TestToAdminAPIErrCode - test for toAdminAPIErrCode helper function.
func TestToAdminAPIErr(t *testing.T) { func TestToAdminAPIErrCode(t *testing.T) {
testCases := []struct { testCases := []struct {
err error err error
expectedAPIErr APIErrorCode expectedAPIErr APIErrorCode

View File

@ -63,8 +63,7 @@ var (
errHealStopSignalled = fmt.Errorf("heal stop signaled") errHealStopSignalled = fmt.Errorf("heal stop signaled")
errFnHealFromAPIErr = func(ctx context.Context, err error) error { errFnHealFromAPIErr = func(ctx context.Context, err error) error {
errCode := toAPIErrorCode(ctx, err) apiErr := toAPIError(ctx, err)
apiErr := getAPIError(errCode)
return fmt.Errorf("Heal internal error: %s: %s", return fmt.Errorf("Heal internal error: %s: %s",
apiErr.Code, apiErr.Description) apiErr.Code, apiErr.Description)
} }
@ -150,7 +149,7 @@ func (ahs *allHealState) getHealSequence(path string) (h *healSequence, exists b
return h, exists return h, exists
} }
func (ahs *allHealState) stopHealSequence(path string) ([]byte, APIErrorCode) { func (ahs *allHealState) stopHealSequence(path string) ([]byte, APIError) {
var hsp madmin.HealStopSuccess var hsp madmin.HealStopSuccess
he, exists := ahs.getHealSequence(path) he, exists := ahs.getHealSequence(path)
if !exists { if !exists {
@ -176,7 +175,7 @@ func (ahs *allHealState) stopHealSequence(path string) ([]byte, APIErrorCode) {
} }
b, err := json.Marshal(&hsp) b, err := json.Marshal(&hsp)
return b, toAdminAPIErrCode(context.Background(), err) return b, toAdminAPIErr(context.Background(), err)
} }
// LaunchNewHealSequence - launches a background routine that performs // LaunchNewHealSequence - launches a background routine that performs
@ -190,7 +189,7 @@ func (ahs *allHealState) stopHealSequence(path string) ([]byte, APIErrorCode) {
// background routine to clean up heal results after the // background routine to clean up heal results after the
// aforementioned duration. // aforementioned duration.
func (ahs *allHealState) LaunchNewHealSequence(h *healSequence) ( func (ahs *allHealState) LaunchNewHealSequence(h *healSequence) (
respBytes []byte, errCode APIErrorCode, errMsg string) { respBytes []byte, apiErr APIError, errMsg string) {
existsAndLive := false existsAndLive := false
he, exists := ahs.getHealSequence(h.path) he, exists := ahs.getHealSequence(h.path)
@ -213,8 +212,7 @@ func (ahs *allHealState) LaunchNewHealSequence(h *healSequence) (
"(use force-start option to stop and start afresh). " + "(use force-start option to stop and start afresh). " +
fmt.Sprintf("The heal was started by IP %s at %s, token is %s", fmt.Sprintf("The heal was started by IP %s at %s, token is %s",
h.clientAddress, h.startTime.Format(http.TimeFormat), h.clientToken) h.clientAddress, h.startTime.Format(http.TimeFormat), h.clientToken)
return nil, errorCodes.ToAPIErr(ErrHealAlreadyRunning), errMsg
return nil, ErrHealAlreadyRunning, errMsg
} }
} }
@ -229,7 +227,7 @@ func (ahs *allHealState) LaunchNewHealSequence(h *healSequence) (
errMsg = "The provided heal sequence path overlaps with an existing " + errMsg = "The provided heal sequence path overlaps with an existing " +
fmt.Sprintf("heal path: %s", k) fmt.Sprintf("heal path: %s", k)
return nil, ErrHealOverlappingPaths, errMsg return nil, errorCodes.ToAPIErr(ErrHealOverlappingPaths), errMsg
} }
} }
@ -246,9 +244,9 @@ func (ahs *allHealState) LaunchNewHealSequence(h *healSequence) (
}) })
if err != nil { if err != nil {
logger.LogIf(h.ctx, err) logger.LogIf(h.ctx, err)
return nil, ErrInternalError, "" return nil, toAPIError(h.ctx, err), ""
} }
return b, ErrNone, "" return b, noError, ""
} }
// PopHealStatusJSON - Called by heal-status API. It fetches the heal // PopHealStatusJSON - Called by heal-status API. It fetches the heal

View File

@ -22,6 +22,11 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/Azure/azure-sdk-for-go/storage"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"google.golang.org/api/googleapi"
minio "github.com/minio/minio-go"
"github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/crypto"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/auth"
@ -212,7 +217,7 @@ const (
ErrHealOverlappingPaths ErrHealOverlappingPaths
ErrIncorrectContinuationToken ErrIncorrectContinuationToken
//S3 Select Errors // S3 Select Errors
ErrEmptyRequestBody ErrEmptyRequestBody
ErrUnsupportedFunction ErrUnsupportedFunction
ErrInvalidExpressionType ErrInvalidExpressionType
@ -304,9 +309,19 @@ const (
ErrAddUserInvalidArgument ErrAddUserInvalidArgument
) )
type errorCodeMap map[APIErrorCode]APIError
func (e errorCodeMap) ToAPIErr(errCode APIErrorCode) APIError {
apiErr, ok := e[errCode]
if !ok {
return e[ErrInternalError]
}
return apiErr
}
// error code to APIError structure, these fields carry respective // error code to APIError structure, these fields carry respective
// descriptions for all the error responses. // descriptions for all the error responses.
var errorCodeResponse = map[APIErrorCode]APIError{ var errorCodes = errorCodeMap{
ErrInvalidCopyDest: { ErrInvalidCopyDest: {
Code: "InvalidRequest", Code: "InvalidRequest",
Description: "This copy request is illegal because it is trying to copy an object to itself without changing the object's metadata, storage class, website redirect location or encryption attributes.", Description: "This copy request is illegal because it is trying to copy an object to itself without changing the object's metadata, storage class, website redirect location or encryption attributes.",
@ -1636,12 +1651,66 @@ func toAPIErrorCode(ctx context.Context, err error) (apiErr APIErrorCode) {
return apiErr return apiErr
} }
var noError = APIError{}
// toAPIError - Converts embedded errors. Convenience
// function written to handle all cases where we have known types of
// errors returned by underlying layers.
func toAPIError(ctx context.Context, err error) APIError {
if err == nil {
return noError
}
var apiErr = errorCodes.ToAPIErr(toAPIErrorCode(ctx, err))
if apiErr.Code == "InternalError" {
// If we see an internal error try to interpret
// any underlying errors if possible depending on
// their internal error types. This code is only
// useful with gateway implementations.
switch e := err.(type) {
case minio.ErrorResponse:
apiErr = APIError{
Code: e.Code,
Description: e.Message,
HTTPStatusCode: e.StatusCode,
}
case *googleapi.Error:
apiErr = APIError{
Code: "XGCSInternalError",
Description: e.Message,
HTTPStatusCode: e.Code,
}
// GCS may send multiple errors, just pick the first one
// since S3 only sends one Error XML response.
if len(e.Errors) >= 1 {
apiErr.Code = e.Errors[0].Reason
}
case storage.AzureStorageServiceError:
apiErr = APIError{
Code: e.Code,
Description: e.Message,
HTTPStatusCode: e.StatusCode,
}
case oss.ServiceError:
apiErr = APIError{
Code: e.Code,
Description: e.Message,
HTTPStatusCode: e.StatusCode,
}
// Add more Gateway SDKs here if any in future.
}
}
return apiErr
}
// getAPIError provides API Error for input API error code. // getAPIError provides API Error for input API error code.
func getAPIError(code APIErrorCode) APIError { func getAPIError(code APIErrorCode) APIError {
if apiErr, ok := errorCodeResponse[code]; ok { if apiErr, ok := errorCodes[code]; ok {
return apiErr return apiErr
} }
return errorCodeResponse[ErrInternalError] return errorCodes.ToAPIErr(ErrInternalError)
} }
// getErrorResponse gets in standard error and resource value and // getErrorResponse gets in standard error and resource value and

View File

@ -25,7 +25,7 @@ import (
"github.com/minio/minio/pkg/hash" "github.com/minio/minio/pkg/hash"
) )
var toAPIErrorCodeTests = []struct { var toAPIErrorTests = []struct {
err error err error
errCode APIErrorCode errCode APIErrorCode
}{ }{
@ -66,7 +66,7 @@ var toAPIErrorCodeTests = []struct {
func TestAPIErrCode(t *testing.T) { func TestAPIErrCode(t *testing.T) {
ctx := context.Background() ctx := context.Background()
for i, testCase := range toAPIErrorCodeTests { for i, testCase := range toAPIErrorTests {
errCode := toAPIErrorCode(ctx, testCase.err) errCode := toAPIErrorCode(ctx, testCase.err)
if errCode != testCase.errCode { if errCode != testCase.errCode {
t.Errorf("Test %d: Expected error code %d, got %d", i+1, testCase.errCode, errCode) t.Errorf("Test %d: Expected error code %d, got %d", i+1, testCase.errCode, errCode)

View File

@ -45,7 +45,7 @@ type completeMultipartAPIError struct {
// of this function. // of this function.
func writePartSmallErrorResponse(w http.ResponseWriter, r *http.Request, err PartTooSmall) { func writePartSmallErrorResponse(w http.ResponseWriter, r *http.Request, err PartTooSmall) {
apiError := getAPIError(toAPIErrorCode(context.Background(), err)) apiError := toAPIError(context.Background(), err)
// Generate complete multipart error response. // Generate complete multipart error response.
errorResponse := getAPIErrorResponse(apiError, r.URL.Path, w.Header().Get(responseRequestIDKey)) errorResponse := getAPIErrorResponse(apiError, r.URL.Path, w.Header().Get(responseRequestIDKey))
cmpErrResp := completeMultipartAPIError{err.PartSize, int64(5242880), err.PartNumber, err.PartETag, errorResponse} cmpErrResp := completeMultipartAPIError{err.PartSize, int64(5242880), err.PartNumber, err.PartETag, errorResponse}

View File

@ -568,13 +568,13 @@ func writeSuccessResponseHeadersOnly(w http.ResponseWriter) {
} }
// writeErrorRespone writes error headers // writeErrorRespone writes error headers
func writeErrorResponse(w http.ResponseWriter, errorCode APIErrorCode, reqURL *url.URL, browser bool) { func writeErrorResponse(w http.ResponseWriter, err APIError, reqURL *url.URL, browser bool) {
switch errorCode { switch err.Code {
case ErrSlowDown, ErrServerNotInitialized, ErrReadQuorum, ErrWriteQuorum: case "SlowDown", "XMinioServerNotInitialized", "XMinioReadQuorum", "XMinioWriteQuorum":
// Set retry-after header to indicate user-agents to retry request after 120secs. // Set retry-after header to indicate user-agents to retry request after 120secs.
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
w.Header().Set("Retry-After", "120") w.Header().Set("Retry-After", "120")
case ErrAccessDenied: case "AccessDenied":
// The request is from browser and also if browser // The request is from browser and also if browser
// is enabled we need to redirect. // is enabled we need to redirect.
if browser && globalIsBrowserEnabled { if browser && globalIsBrowserEnabled {
@ -584,42 +584,38 @@ func writeErrorResponse(w http.ResponseWriter, errorCode APIErrorCode, reqURL *u
} }
} }
apiError := getAPIError(errorCode)
// Generate error response. // Generate error response.
errorResponse := getAPIErrorResponse(apiError, reqURL.Path, w.Header().Get(responseRequestIDKey)) errorResponse := getAPIErrorResponse(err, reqURL.Path, w.Header().Get(responseRequestIDKey))
encodedErrorResponse := encodeResponse(errorResponse) encodedErrorResponse := encodeResponse(errorResponse)
writeResponse(w, apiError.HTTPStatusCode, encodedErrorResponse, mimeXML) writeResponse(w, err.HTTPStatusCode, encodedErrorResponse, mimeXML)
} }
func writeErrorResponseHeadersOnly(w http.ResponseWriter, errorCode APIErrorCode) { func writeErrorResponseHeadersOnly(w http.ResponseWriter, err APIError) {
apiError := getAPIError(errorCode) writeResponse(w, err.HTTPStatusCode, nil, mimeNone)
writeResponse(w, apiError.HTTPStatusCode, nil, mimeNone)
} }
// writeErrorResponseJSON - writes error response in JSON format; // writeErrorResponseJSON - writes error response in JSON format;
// useful for admin APIs. // useful for admin APIs.
func writeErrorResponseJSON(w http.ResponseWriter, errorCode APIErrorCode, reqURL *url.URL) { func writeErrorResponseJSON(w http.ResponseWriter, err APIError, reqURL *url.URL) {
apiError := getAPIError(errorCode)
// Generate error response. // Generate error response.
errorResponse := getAPIErrorResponse(apiError, reqURL.Path, w.Header().Get(responseRequestIDKey)) errorResponse := getAPIErrorResponse(err, reqURL.Path, w.Header().Get(responseRequestIDKey))
encodedErrorResponse := encodeResponseJSON(errorResponse) encodedErrorResponse := encodeResponseJSON(errorResponse)
writeResponse(w, apiError.HTTPStatusCode, encodedErrorResponse, mimeJSON) writeResponse(w, err.HTTPStatusCode, encodedErrorResponse, mimeJSON)
} }
// writeCustomErrorResponseJSON - similar to writeErrorResponseJSON, // writeCustomErrorResponseJSON - similar to writeErrorResponseJSON,
// but accepts the error message directly (this allows messages to be // but accepts the error message directly (this allows messages to be
// dynamically generated.) // dynamically generated.)
func writeCustomErrorResponseJSON(w http.ResponseWriter, errorCode APIErrorCode, func writeCustomErrorResponseJSON(w http.ResponseWriter, err APIError,
errBody string, reqURL *url.URL) { errBody string, reqURL *url.URL) {
apiError := getAPIError(errorCode)
errorResponse := APIErrorResponse{ errorResponse := APIErrorResponse{
Code: apiError.Code, Code: err.Code,
Message: errBody, Message: errBody,
Resource: reqURL.Path, Resource: reqURL.Path,
RequestID: w.Header().Get(responseRequestIDKey), RequestID: w.Header().Get(responseRequestIDKey),
HostID: "3L137", HostID: "3L137",
} }
encodedErrorResponse := encodeResponseJSON(errorResponse) encodedErrorResponse := encodeResponseJSON(errorResponse)
writeResponse(w, apiError.HTTPStatusCode, encodedErrorResponse, mimeJSON) writeResponse(w, err.HTTPStatusCode, encodedErrorResponse, mimeJSON)
} }

View File

@ -416,7 +416,7 @@ func (a authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
a.handler.ServeHTTP(w, r) a.handler.ServeHTTP(w, r)
return return
} }
writeErrorResponse(w, ErrSignatureVersionNotSupported, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrSignatureVersionNotSupported), r.URL, guessIsBrowserReq(r))
} }
// isPutAllowed - check if PUT operation is allowed on the resource, this // isPutAllowed - check if PUT operation is allowed on the resource, this

View File

@ -383,7 +383,7 @@ func TestIsReqAuthenticated(t *testing.T) {
for i, testCase := range testCases { for i, testCase := range testCases {
if s3Error := isReqAuthenticated(ctx, testCase.req, globalServerConfig.GetRegion()); s3Error != testCase.s3Error { if s3Error := isReqAuthenticated(ctx, testCase.req, globalServerConfig.GetRegion()); s3Error != testCase.s3Error {
if _, err := ioutil.ReadAll(testCase.req.Body); toAPIErrorCode(ctx, err) != testCase.s3Error { if _, err := ioutil.ReadAll(testCase.req.Body); toAPIErrorCode(ctx, err) != testCase.s3Error {
t.Fatalf("Test %d: Unexpected S3 error: want %d - got %d (got after reading request %d)", i, testCase.s3Error, s3Error, toAPIErrorCode(ctx, err)) t.Fatalf("Test %d: Unexpected S3 error: want %d - got %d (got after reading request %s)", i, testCase.s3Error, s3Error, toAPIError(ctx, err).Code)
} }
} }
} }

View File

@ -66,12 +66,12 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
@ -79,18 +79,18 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http
// Extract all the listObjectsV2 query params to their native values. // Extract all the listObjectsV2 query params to their native values.
prefix, token, startAfter, delimiter, fetchOwner, maxKeys, _, errCode := getListObjectsV2Args(urlValues) prefix, token, startAfter, delimiter, fetchOwner, maxKeys, _, errCode := getListObjectsV2Args(urlValues)
if errCode != ErrNone { if errCode != ErrNone {
writeErrorResponse(w, errCode, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(errCode), r.URL, guessIsBrowserReq(r))
return return
} }
// Validate the query params before beginning to serve the request. // Validate the query params before beginning to serve the request.
// fetch-owner is not validated since it is a boolean // fetch-owner is not validated since it is a boolean
if s3Error := validateListObjectsArgs(prefix, token, delimiter, maxKeys); s3Error != ErrNone { if s3Error := validateListObjectsArgs(prefix, token, delimiter, maxKeys); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
listObjectsV2 := objectAPI.ListObjectsV2 listObjectsV2 := objectAPI.ListObjectsV2
if api.CacheAPI() != nil { if api.CacheAPI() != nil {
listObjectsV2 = api.CacheAPI().ListObjectsV2 listObjectsV2 = api.CacheAPI().ListObjectsV2
@ -100,7 +100,7 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http
// marshaled into S3 compatible XML header. // marshaled into S3 compatible XML header.
listObjectsV2Info, err := listObjectsV2(ctx, bucket, prefix, token, delimiter, maxKeys, fetchOwner, startAfter) listObjectsV2Info, err := listObjectsV2(ctx, bucket, prefix, token, delimiter, maxKeys, fetchOwner, startAfter)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -110,7 +110,7 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http
// Read the decompressed size from the meta.json. // Read the decompressed size from the meta.json.
actualSize = listObjectsV2Info.Objects[i].GetActualSize() actualSize = listObjectsV2Info.Objects[i].GetActualSize()
if actualSize < 0 { if actualSize < 0 {
writeErrorResponse(w, ErrInvalidDecompressedSize, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInvalidDecompressedSize), r.URL, guessIsBrowserReq(r))
return return
} }
// Set the info.Size to the actualSize. // Set the info.Size to the actualSize.
@ -119,7 +119,7 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http
listObjectsV2Info.Objects[i].ETag = getDecryptedETag(r.Header, listObjectsV2Info.Objects[i], false) listObjectsV2Info.Objects[i].ETag = getDecryptedETag(r.Header, listObjectsV2Info.Objects[i], false)
listObjectsV2Info.Objects[i].Size, err = listObjectsV2Info.Objects[i].DecryptedSize() listObjectsV2Info.Objects[i].Size, err = listObjectsV2Info.Objects[i].DecryptedSize()
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
} }
@ -148,42 +148,39 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Extract all the litsObjectsV1 query params to their native values. // Extract all the litsObjectsV1 query params to their native values.
prefix, marker, delimiter, maxKeys, _, s3Error := getListObjectsV1Args(r.URL.Query()) prefix, marker, delimiter, maxKeys, _, s3Error := getListObjectsV1Args(r.URL.Query())
if s3Error != ErrNone { if s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Validate the maxKeys lowerbound. When maxKeys > 1000, S3 returns 1000 but // Validate all the query params before beginning to serve the request.
// does not throw an error.
if maxKeys < 0 {
writeErrorResponse(w, ErrInvalidMaxKeys, r.URL, guessIsBrowserReq(r))
return
} // Validate all the query params before beginning to serve the request.
if s3Error := validateListObjectsArgs(prefix, marker, delimiter, maxKeys); s3Error != ErrNone { if s3Error := validateListObjectsArgs(prefix, marker, delimiter, maxKeys); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
listObjects := objectAPI.ListObjects listObjects := objectAPI.ListObjects
if api.CacheAPI() != nil { if api.CacheAPI() != nil {
listObjects = api.CacheAPI().ListObjects listObjects = api.CacheAPI().ListObjects
} }
// Inititate a list objects operation based on the input params. // Inititate a list objects operation based on the input params.
// On success would return back ListObjectsInfo object to be // On success would return back ListObjectsInfo object to be
// marshaled into S3 compatible XML header. // marshaled into S3 compatible XML header.
listObjectsInfo, err := listObjects(ctx, bucket, prefix, marker, delimiter, maxKeys) listObjectsInfo, err := listObjects(ctx, bucket, prefix, marker, delimiter, maxKeys)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -193,7 +190,7 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http
// Read the decompressed size from the meta.json. // Read the decompressed size from the meta.json.
actualSize = listObjectsInfo.Objects[i].GetActualSize() actualSize = listObjectsInfo.Objects[i].GetActualSize()
if actualSize < 0 { if actualSize < 0 {
writeErrorResponse(w, ErrInvalidDecompressedSize, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInvalidDecompressedSize), r.URL, guessIsBrowserReq(r))
return return
} }
// Set the info.Size to the actualSize. // Set the info.Size to the actualSize.
@ -202,7 +199,7 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http
listObjectsInfo.Objects[i].ETag = getDecryptedETag(r.Header, listObjectsInfo.Objects[i], false) listObjectsInfo.Objects[i].ETag = getDecryptedETag(r.Header, listObjectsInfo.Objects[i], false)
listObjectsInfo.Objects[i].Size, err = listObjectsInfo.Objects[i].DecryptedSize() listObjectsInfo.Objects[i].Size, err = listObjectsInfo.Objects[i].DecryptedSize()
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
} }

View File

@ -96,12 +96,12 @@ func (api objectAPIHandlers) GetBucketLocationHandler(w http.ResponseWriter, r *
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketLocationAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketLocationAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
@ -110,7 +110,7 @@ func (api objectAPIHandlers) GetBucketLocationHandler(w http.ResponseWriter, r *
getBucketInfo = api.CacheAPI().GetBucketInfo getBucketInfo = api.CacheAPI().GetBucketInfo
} }
if _, err := getBucketInfo(ctx, bucket); err != nil { if _, err := getBucketInfo(ctx, bucket); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -146,35 +146,37 @@ func (api objectAPIHandlers) ListMultipartUploadsHandler(w http.ResponseWriter,
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketMultipartUploadsAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketMultipartUploadsAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
prefix, keyMarker, uploadIDMarker, delimiter, maxUploads, _, s3Error := getBucketMultipartResources(r.URL.Query()) prefix, keyMarker, uploadIDMarker, delimiter, maxUploads, _, errCode := getBucketMultipartResources(r.URL.Query())
if s3Error != ErrNone { if errCode != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(errCode), r.URL, guessIsBrowserReq(r))
return return
} }
if maxUploads < 0 { if maxUploads < 0 {
writeErrorResponse(w, ErrInvalidMaxUploads, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInvalidMaxUploads), r.URL, guessIsBrowserReq(r))
return return
} }
if keyMarker != "" { if keyMarker != "" {
// Marker not common with prefix is not implemented. // Marker not common with prefix is not implemented.
if !hasPrefix(keyMarker, prefix) { if !hasPrefix(keyMarker, prefix) {
writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
return return
} }
} }
listMultipartsInfo, err := objectAPI.ListMultipartUploads(ctx, bucket, prefix, keyMarker, uploadIDMarker, delimiter, maxUploads) listMultipartsInfo, err := objectAPI.ListMultipartUploads(ctx, bucket, prefix, keyMarker, uploadIDMarker, delimiter, maxUploads)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
// generate response // generate response
@ -196,25 +198,26 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
listBuckets := objectAPI.ListBuckets
listBuckets := objectAPI.ListBuckets
if api.CacheAPI() != nil { if api.CacheAPI() != nil {
listBuckets = api.CacheAPI().ListBuckets listBuckets = api.CacheAPI().ListBuckets
} }
if s3Error := checkRequestAuthType(ctx, r, policy.ListAllMyBucketsAction, "", ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.ListAllMyBucketsAction, "", ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// If etcd, dns federation configured list buckets from etcd. // If etcd, dns federation configured list buckets from etcd.
var bucketsInfo []BucketInfo var bucketsInfo []BucketInfo
if globalDNSConfig != nil { if globalDNSConfig != nil {
dnsBuckets, err := globalDNSConfig.List() dnsBuckets, err := globalDNSConfig.List()
if err != nil && err != dns.ErrNoEntriesFound { if err != nil && err != dns.ErrNoEntriesFound {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
bucketSet := set.NewStringSet() bucketSet := set.NewStringSet()
@ -233,7 +236,7 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R
var err error var err error
bucketsInfo, err = listBuckets(ctx) bucketsInfo, err = listBuckets(ctx)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
} }
@ -257,7 +260,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
@ -266,7 +269,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
// In the event access is denied, a 200 response should still be returned // In the event access is denied, a 200 response should still be returned
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html // http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
if s3Error != ErrAccessDenied { if s3Error != ErrAccessDenied {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
} }
@ -274,14 +277,14 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
// 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, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMissingContentLength), r.URL, guessIsBrowserReq(r))
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, ErrMissingContentMD5, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMissingContentMD5), r.URL, guessIsBrowserReq(r))
return return
} }
@ -297,7 +300,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
// Read incoming body XML bytes. // Read incoming body XML bytes.
if _, err := io.ReadFull(r.Body, deleteXMLBytes); err != nil { if _, err := io.ReadFull(r.Body, deleteXMLBytes); err != nil {
logger.LogIf(ctx, err) logger.LogIf(ctx, err)
writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAdminAPIErr(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -305,7 +308,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
deleteObjects := &DeleteObjectsRequest{} deleteObjects := &DeleteObjectsRequest{}
if err := xml.Unmarshal(deleteXMLBytes, deleteObjects); err != nil { if err := xml.Unmarshal(deleteXMLBytes, deleteObjects); err != nil {
logger.LogIf(ctx, err) logger.LogIf(ctx, err)
writeErrorResponse(w, ErrMalformedXML, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMalformedXML), r.URL, guessIsBrowserReq(r))
return return
} }
@ -313,7 +316,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
if globalWORMEnabled { if globalWORMEnabled {
// Not required to check whether given objects exist or not, because // Not required to check whether given objects exist or not, because
// DeleteMultipleObject is always successful irrespective of object existence. // DeleteMultipleObject is always successful irrespective of object existence.
writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL, guessIsBrowserReq(r))
return return
} }
@ -352,10 +355,11 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
deletedObjects = append(deletedObjects, object) deletedObjects = append(deletedObjects, object)
continue continue
} }
apiErr := toAPIError(ctx, err)
// Error during delete should be collected separately. // Error during delete should be collected separately.
deleteErrors = append(deleteErrors, DeleteError{ deleteErrors = append(deleteErrors, DeleteError{
Code: errorCodeResponse[toAPIErrorCode(ctx, err)].Code, Code: apiErr.Code,
Message: errorCodeResponse[toAPIErrorCode(ctx, err)].Description, Message: apiErr.Description,
Key: object.ObjectName, Key: object.ObjectName,
}) })
} }
@ -401,7 +405,7 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
@ -409,21 +413,21 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req
bucket := vars["bucket"] bucket := vars["bucket"]
if s3Error := checkRequestAuthType(ctx, r, policy.CreateBucketAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.CreateBucketAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Parse incoming location constraint. // Parse incoming location constraint.
location, s3Error := parseLocationConstraint(r) location, s3Error := parseLocationConstraint(r)
if s3Error != ErrNone { if s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Validate if location sent by the client is valid, reject // Validate if location sent by the client is valid, reject
// requests which do not follow valid region requirements. // requests which do not follow valid region requirements.
if !isValidLocation(location) { if !isValidLocation(location) {
writeErrorResponse(w, ErrInvalidRegion, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInvalidRegion), r.URL, guessIsBrowserReq(r))
return return
} }
@ -432,12 +436,12 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req
if err == dns.ErrNoEntriesFound { if err == dns.ErrNoEntriesFound {
// Proceed to creating a bucket. // Proceed to creating a bucket.
if err = objectAPI.MakeBucketWithLocation(ctx, bucket, location); err != nil { if err = objectAPI.MakeBucketWithLocation(ctx, bucket, location); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
if err = globalDNSConfig.Put(bucket); err != nil { if err = globalDNSConfig.Put(bucket); err != nil {
objectAPI.DeleteBucket(ctx, bucket) objectAPI.DeleteBucket(ctx, bucket)
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -447,18 +451,18 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req
writeSuccessResponseHeadersOnly(w) writeSuccessResponseHeadersOnly(w)
return return
} }
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
writeErrorResponse(w, ErrBucketAlreadyOwnedByYou, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrBucketAlreadyOwnedByYou), r.URL, guessIsBrowserReq(r))
return return
} }
// Proceed to creating a bucket. // Proceed to creating a bucket.
err := objectAPI.MakeBucketWithLocation(ctx, bucket, location) err := objectAPI.MakeBucketWithLocation(ctx, bucket, location)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -479,33 +483,36 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
if crypto.S3KMS.IsRequested(r.Header) { // SSE-KMS is not supported if crypto.S3KMS.IsRequested(r.Header) { // SSE-KMS is not supported
writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
return return
} }
if !api.EncryptionEnabled() && hasServerSideEncryptionHeader(r.Header) { if !api.EncryptionEnabled() && hasServerSideEncryptionHeader(r.Header) {
writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
return return
} }
bucket := mux.Vars(r)["bucket"] bucket := mux.Vars(r)["bucket"]
// Require Content-Length to be set in the request // Require Content-Length to be set in the request
size := r.ContentLength size := r.ContentLength
if size < 0 { if size < 0 {
writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMissingContentLength), r.URL, guessIsBrowserReq(r))
return return
} }
resource, err := getResource(r.URL.Path, r.Host, globalDomainName) resource, err := getResource(r.URL.Path, r.Host, globalDomainName)
if err != nil { if err != nil {
writeErrorResponse(w, ErrInvalidRequest, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL, guessIsBrowserReq(r))
return return
} }
// Make sure that the URL does not contain object name. // Make sure that the URL does not contain object name.
if bucket != filepath.Clean(resource[1:]) { if bucket != filepath.Clean(resource[1:]) {
writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL, guessIsBrowserReq(r))
return return
} }
@ -514,7 +521,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
reader, err := r.MultipartReader() reader, err := r.MultipartReader()
if err != nil { if err != nil {
logger.LogIf(ctx, err) logger.LogIf(ctx, err)
writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMalformedPOSTRequest), r.URL, guessIsBrowserReq(r))
return return
} }
@ -522,7 +529,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
form, err := reader.ReadForm(maxFormMemory) form, err := reader.ReadForm(maxFormMemory)
if err != nil { if err != nil {
logger.LogIf(ctx, err) logger.LogIf(ctx, err)
writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMalformedPOSTRequest), r.URL, guessIsBrowserReq(r))
return return
} }
@ -533,13 +540,13 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
fileBody, fileName, fileSize, formValues, err := extractPostPolicyFormValues(ctx, form) fileBody, fileName, fileSize, formValues, err := extractPostPolicyFormValues(ctx, form)
if err != nil { if err != nil {
logger.LogIf(ctx, err) logger.LogIf(ctx, err)
writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMalformedPOSTRequest), r.URL, guessIsBrowserReq(r))
return return
} }
// Check if file is provided, error out otherwise. // Check if file is provided, error out otherwise.
if fileBody == nil { if fileBody == nil {
writeErrorResponse(w, ErrPOSTFileRequired, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrPOSTFileRequired), r.URL, guessIsBrowserReq(r))
return return
} }
@ -561,21 +568,21 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
if successRedirect != "" { if successRedirect != "" {
redirectURL, err = url.Parse(successRedirect) redirectURL, err = url.Parse(successRedirect)
if err != nil { if err != nil {
writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMalformedPOSTRequest), r.URL, guessIsBrowserReq(r))
return return
} }
} }
// Verify policy signature. // Verify policy signature.
apiErr := doesPolicySignatureMatch(formValues) errCode := doesPolicySignatureMatch(formValues)
if apiErr != ErrNone { if errCode != ErrNone {
writeErrorResponse(w, apiErr, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(errCode), r.URL, guessIsBrowserReq(r))
return return
} }
policyBytes, err := base64.StdEncoding.DecodeString(formValues.Get("Policy")) policyBytes, err := base64.StdEncoding.DecodeString(formValues.Get("Policy"))
if err != nil { if err != nil {
writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMalformedPOSTRequest), r.URL, guessIsBrowserReq(r))
return return
} }
@ -583,13 +590,13 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
if len(policyBytes) > 0 { if len(policyBytes) > 0 {
postPolicyForm, err := parsePostPolicyForm(string(policyBytes)) postPolicyForm, err := parsePostPolicyForm(string(policyBytes))
if err != nil { if err != nil {
writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMalformedPOSTRequest), r.URL, guessIsBrowserReq(r))
return return
} }
// Make sure formValues adhere to policy restrictions. // Make sure formValues adhere to policy restrictions.
if apiErr = checkPostPolicy(formValues, postPolicyForm); apiErr != ErrNone { if errCode = checkPostPolicy(formValues, postPolicyForm); errCode != ErrNone {
writeErrorResponse(w, apiErr, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(errCode), r.URL, guessIsBrowserReq(r))
return return
} }
@ -598,12 +605,12 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
lengthRange := postPolicyForm.Conditions.ContentLengthRange lengthRange := postPolicyForm.Conditions.ContentLengthRange
if lengthRange.Valid { if lengthRange.Valid {
if fileSize < lengthRange.Min { if fileSize < lengthRange.Min {
writeErrorResponse(w, toAPIErrorCode(ctx, errDataTooSmall), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, errDataTooSmall), r.URL, guessIsBrowserReq(r))
return return
} }
if fileSize > lengthRange.Max || isMaxObjectSize(fileSize) { if fileSize > lengthRange.Max || isMaxObjectSize(fileSize) {
writeErrorResponse(w, toAPIErrorCode(ctx, errDataTooLarge), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, errDataTooLarge), r.URL, guessIsBrowserReq(r))
return return
} }
} }
@ -613,14 +620,14 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
metadata := make(map[string]string) metadata := make(map[string]string)
err = extractMetadataFromMap(ctx, formValues, metadata) err = extractMetadataFromMap(ctx, formValues, metadata)
if err != nil { if err != nil {
writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
hashReader, err := hash.NewReader(fileBody, fileSize, "", "", fileSize) hashReader, err := hash.NewReader(fileBody, fileSize, "", "", fileSize)
if err != nil { if err != nil {
logger.LogIf(ctx, err) logger.LogIf(ctx, err)
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
rawReader := hashReader rawReader := hashReader
@ -635,7 +642,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
var opts ObjectOptions var opts ObjectOptions
opts, err = putOpts(ctx, r, bucket, object, metadata) opts, err = putOpts(ctx, r, bucket, object, metadata)
if err != nil { if err != nil {
writeErrorResponseHeadersOnly(w, toAPIErrorCode(ctx, err)) writeErrorResponseHeadersOnly(w, toAPIError(ctx, err))
return return
} }
if objectAPI.IsEncryptionSupported() { if objectAPI.IsEncryptionSupported() {
@ -645,19 +652,19 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
if crypto.SSEC.IsRequested(formValues) { if crypto.SSEC.IsRequested(formValues) {
key, err = ParseSSECustomerHeader(formValues) key, err = ParseSSECustomerHeader(formValues)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
} }
reader, objectEncryptionKey, err = newEncryptReader(hashReader, key, bucket, object, metadata, crypto.S3.IsRequested(formValues)) reader, objectEncryptionKey, err = newEncryptReader(hashReader, key, bucket, object, metadata, crypto.S3.IsRequested(formValues))
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
info := ObjectInfo{Size: fileSize} info := ObjectInfo{Size: fileSize}
hashReader, err = hash.NewReader(reader, info.EncryptedSize(), "", "", fileSize) // do not try to verify encrypted content hashReader, err = hash.NewReader(reader, info.EncryptedSize(), "", "", fileSize) // do not try to verify encrypted content
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
pReader = NewPutObjReader(rawReader, hashReader, objectEncryptionKey) pReader = NewPutObjReader(rawReader, hashReader, objectEncryptionKey)
@ -666,7 +673,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
objInfo, err := objectAPI.PutObject(ctx, bucket, object, pReader, opts) objInfo, err := objectAPI.PutObject(ctx, bucket, object, pReader, opts)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -732,12 +739,12 @@ func (api objectAPIHandlers) HeadBucketHandler(w http.ResponseWriter, r *http.Re
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponseHeadersOnly(w, ErrServerNotInitialized) writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(ErrServerNotInitialized))
return return
} }
if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone {
writeErrorResponseHeadersOnly(w, s3Error) writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(s3Error))
return return
} }
@ -746,7 +753,7 @@ func (api objectAPIHandlers) HeadBucketHandler(w http.ResponseWriter, r *http.Re
getBucketInfo = api.CacheAPI().GetBucketInfo getBucketInfo = api.CacheAPI().GetBucketInfo
} }
if _, err := getBucketInfo(ctx, bucket); err != nil { if _, err := getBucketInfo(ctx, bucket); err != nil {
writeErrorResponseHeadersOnly(w, toAPIErrorCode(ctx, err)) writeErrorResponseHeadersOnly(w, toAPIError(ctx, err))
return return
} }
@ -764,12 +771,12 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http.
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
if s3Error := checkRequestAuthType(ctx, r, policy.DeleteBucketAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.DeleteBucketAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
@ -779,7 +786,7 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http.
} }
// Attempt to delete bucket. // Attempt to delete bucket.
if err := deleteBucket(ctx, bucket); err != nil { if err := deleteBucket(ctx, bucket); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -791,7 +798,7 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http.
if err := globalDNSConfig.Delete(bucket); err != nil { if err := globalDNSConfig.Delete(bucket); err != nil {
// Deleting DNS entry failed, attempt to create the bucket again. // Deleting DNS entry failed, attempt to create the bucket again.
objectAPI.MakeBucketWithLocation(ctx, bucket, "") objectAPI.MakeBucketWithLocation(ctx, bucket, "")
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
} }

View File

@ -645,8 +645,8 @@ func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketNa
getDeleteErrorList := func(objects []ObjectIdentifier) (deleteErrorList []DeleteError) { getDeleteErrorList := func(objects []ObjectIdentifier) (deleteErrorList []DeleteError) {
for _, obj := range objects { for _, obj := range objects {
deleteErrorList = append(deleteErrorList, DeleteError{ deleteErrorList = append(deleteErrorList, DeleteError{
Code: errorCodeResponse[ErrAccessDenied].Code, Code: errorCodes[ErrAccessDenied].Code,
Message: errorCodeResponse[ErrAccessDenied].Description, Message: errorCodes[ErrAccessDenied].Description,
Key: obj.ObjectName, Key: obj.ObjectName,
}) })
} }

View File

@ -51,23 +51,23 @@ func (api objectAPIHandlers) GetBucketNotificationHandler(w http.ResponseWriter,
objAPI := api.ObjectAPI() objAPI := api.ObjectAPI()
if objAPI == nil { if objAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
if !objAPI.IsNotificationSupported() { if !objAPI.IsNotificationSupported() {
writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
return return
} }
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketNotificationAction, bucketName, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketNotificationAction, bucketName, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
_, err := objAPI.GetBucketInfo(ctx, bucketName) _, err := objAPI.GetBucketInfo(ctx, bucketName)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -76,7 +76,7 @@ func (api objectAPIHandlers) GetBucketNotificationHandler(w http.ResponseWriter,
if err != nil { if err != nil {
// Ignore errNoSuchNotifications to comply with AWS S3. // Ignore errNoSuchNotifications to comply with AWS S3.
if err != errNoSuchNotifications { if err != errNoSuchNotifications {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -90,7 +90,7 @@ func (api objectAPIHandlers) GetBucketNotificationHandler(w http.ResponseWriter,
notificationBytes, err := xml.Marshal(nConfig) notificationBytes, err := xml.Marshal(nConfig)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -106,12 +106,12 @@ func (api objectAPIHandlers) PutBucketNotificationHandler(w http.ResponseWriter,
objectAPI := api.ObjectAPI() objectAPI := api.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
if !objectAPI.IsNotificationSupported() { if !objectAPI.IsNotificationSupported() {
writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
return return
} }
@ -119,28 +119,28 @@ func (api objectAPIHandlers) PutBucketNotificationHandler(w http.ResponseWriter,
bucketName := vars["bucket"] bucketName := vars["bucket"]
if s3Error := checkRequestAuthType(ctx, r, policy.PutBucketNotificationAction, bucketName, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.PutBucketNotificationAction, bucketName, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
_, err := objectAPI.GetBucketInfo(ctx, bucketName) _, err := objectAPI.GetBucketInfo(ctx, bucketName)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
// PutBucketNotification always needs a Content-Length. // PutBucketNotification always needs a Content-Length.
if r.ContentLength <= 0 { if r.ContentLength <= 0 {
writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMissingContentLength), r.URL, guessIsBrowserReq(r))
return return
} }
var config *event.Config var config *event.Config
config, err = event.ParseConfig(io.LimitReader(r.Body, r.ContentLength), globalServerConfig.GetRegion(), globalNotificationSys.targetList) config, err = event.ParseConfig(io.LimitReader(r.Body, r.ContentLength), globalServerConfig.GetRegion(), globalNotificationSys.targetList)
if err != nil { if err != nil {
apiErr := ErrMalformedXML apiErr := errorCodes.ToAPIErr(ErrMalformedXML)
if event.IsEventError(err) { if event.IsEventError(err) {
apiErr = toAPIErrorCode(ctx, err) apiErr = toAPIError(ctx, err)
} }
writeErrorResponse(w, apiErr, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, apiErr, r.URL, guessIsBrowserReq(r))
@ -148,7 +148,7 @@ func (api objectAPIHandlers) PutBucketNotificationHandler(w http.ResponseWriter,
} }
if err = saveNotificationConfig(ctx, objectAPI, bucketName, config); err != nil { if err = saveNotificationConfig(ctx, objectAPI, bucketName, config); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -169,23 +169,24 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit
// Validate if bucket exists. // Validate if bucket exists.
objAPI := api.ObjectAPI() objAPI := api.ObjectAPI()
if objAPI == nil { if objAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
if !objAPI.IsNotificationSupported() { if !objAPI.IsNotificationSupported() {
writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
return return
} }
if !objAPI.IsListenBucketSupported() { if !objAPI.IsListenBucketSupported() {
writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
return return
} }
vars := mux.Vars(r) vars := mux.Vars(r)
bucketName := vars["bucket"] bucketName := vars["bucket"]
if s3Error := checkRequestAuthType(ctx, r, policy.ListenBucketNotificationAction, bucketName, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.ListenBucketNotificationAction, bucketName, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
@ -193,11 +194,13 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit
var prefix string var prefix string
if len(values["prefix"]) > 1 { if len(values["prefix"]) > 1 {
writeErrorResponse(w, ErrFilterNamePrefix, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrFilterNamePrefix), r.URL, guessIsBrowserReq(r))
return
} }
if len(values["prefix"]) == 1 { if len(values["prefix"]) == 1 {
if err := event.ValidateFilterRuleValue(values["prefix"][0]); err != nil { if err := event.ValidateFilterRuleValue(values["prefix"][0]); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -206,11 +209,13 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit
var suffix string var suffix string
if len(values["suffix"]) > 1 { if len(values["suffix"]) > 1 {
writeErrorResponse(w, ErrFilterNameSuffix, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrFilterNameSuffix), r.URL, guessIsBrowserReq(r))
return
} }
if len(values["suffix"]) == 1 { if len(values["suffix"]) == 1 {
if err := event.ValidateFilterRuleValue(values["suffix"][0]); err != nil { if err := event.ValidateFilterRuleValue(values["suffix"][0]); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -223,7 +228,7 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit
for _, s := range values["events"] { for _, s := range values["events"] {
eventName, err := event.ParseName(s) eventName, err := event.ParseName(s)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -231,19 +236,19 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit
} }
if _, err := objAPI.GetBucketInfo(ctx, bucketName); err != nil { if _, err := objAPI.GetBucketInfo(ctx, bucketName); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
host, err := xnet.ParseHost(r.RemoteAddr) host, err := xnet.ParseHost(r.RemoteAddr)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
target, err := target.NewHTTPClientTarget(*host, w) target, err := target.NewHTTPClientTarget(*host, w)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -251,7 +256,7 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit
if err = globalNotificationSys.AddRemoteTarget(bucketName, target, rulesMap); err != nil { if err = globalNotificationSys.AddRemoteTarget(bucketName, target, rulesMap); err != nil {
logger.GetReqInfo(ctx).AppendTags("target", target.ID().Name) logger.GetReqInfo(ctx).AppendTags("target", target.ID().Name)
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
defer globalNotificationSys.RemoveRemoteTarget(bucketName, target.ID()) defer globalNotificationSys.RemoveRemoteTarget(bucketName, target.ID())
@ -259,13 +264,13 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit
thisAddr, err := xnet.ParseHost(GetLocalPeer(globalEndpoints)) thisAddr, err := xnet.ParseHost(GetLocalPeer(globalEndpoints))
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
if err = SaveListener(objAPI, bucketName, eventNames, pattern, target.ID(), *thisAddr); err != nil { if err = SaveListener(objAPI, bucketName, eventNames, pattern, target.ID(), *thisAddr); err != nil {
logger.GetReqInfo(ctx).AppendTags("target", target.ID().Name) logger.GetReqInfo(ctx).AppendTags("target", target.ID().Name)
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -275,7 +280,7 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit
if err = RemoveListener(objAPI, bucketName, target.ID(), *thisAddr); err != nil { if err = RemoveListener(objAPI, bucketName, target.ID(), *thisAddr); err != nil {
logger.GetReqInfo(ctx).AppendTags("target", target.ID().Name) logger.GetReqInfo(ctx).AppendTags("target", target.ID().Name)
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
} }

View File

@ -44,7 +44,7 @@ func (api objectAPIHandlers) PutBucketPolicyHandler(w http.ResponseWriter, r *ht
objAPI := api.ObjectAPI() objAPI := api.ObjectAPI()
if objAPI == nil { if objAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
@ -52,43 +52,43 @@ func (api objectAPIHandlers) PutBucketPolicyHandler(w http.ResponseWriter, r *ht
bucket := vars["bucket"] bucket := vars["bucket"]
if s3Error := checkRequestAuthType(ctx, r, policy.PutBucketPolicyAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.PutBucketPolicyAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Check if bucket exists. // Check if bucket exists.
if _, err := objAPI.GetBucketInfo(ctx, bucket); err != nil { if _, err := objAPI.GetBucketInfo(ctx, bucket); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
// Error out if Content-Length is missing. // Error out if Content-Length is missing.
// PutBucketPolicy always needs Content-Length. // PutBucketPolicy always needs Content-Length.
if r.ContentLength <= 0 { if r.ContentLength <= 0 {
writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMissingContentLength), r.URL, guessIsBrowserReq(r))
return return
} }
// Error out if Content-Length is beyond allowed size. // Error out if Content-Length is beyond allowed size.
if r.ContentLength > maxBucketPolicySize { if r.ContentLength > maxBucketPolicySize {
writeErrorResponse(w, ErrEntityTooLarge, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrEntityTooLarge), r.URL, guessIsBrowserReq(r))
return return
} }
bucketPolicy, err := policy.ParseConfig(io.LimitReader(r.Body, r.ContentLength), bucket) bucketPolicy, err := policy.ParseConfig(io.LimitReader(r.Body, r.ContentLength), bucket)
if err != nil { if err != nil {
writeErrorResponse(w, ErrMalformedPolicy, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMalformedPolicy), r.URL, guessIsBrowserReq(r))
return return
} }
// Version in policy must not be empty // Version in policy must not be empty
if bucketPolicy.Version == "" { if bucketPolicy.Version == "" {
writeErrorResponse(w, ErrMalformedPolicy, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMalformedPolicy), r.URL, guessIsBrowserReq(r))
return return
} }
if err = objAPI.SetBucketPolicy(ctx, bucket, bucketPolicy); err != nil { if err = objAPI.SetBucketPolicy(ctx, bucket, bucketPolicy); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -107,7 +107,7 @@ func (api objectAPIHandlers) DeleteBucketPolicyHandler(w http.ResponseWriter, r
objAPI := api.ObjectAPI() objAPI := api.ObjectAPI()
if objAPI == nil { if objAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
@ -115,18 +115,18 @@ func (api objectAPIHandlers) DeleteBucketPolicyHandler(w http.ResponseWriter, r
bucket := vars["bucket"] bucket := vars["bucket"]
if s3Error := checkRequestAuthType(ctx, r, policy.DeleteBucketPolicyAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.DeleteBucketPolicyAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Check if bucket exists. // Check if bucket exists.
if _, err := objAPI.GetBucketInfo(ctx, bucket); err != nil { if _, err := objAPI.GetBucketInfo(ctx, bucket); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
if err := objAPI.DeleteBucketPolicy(ctx, bucket); err != nil { if err := objAPI.DeleteBucketPolicy(ctx, bucket); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -145,7 +145,7 @@ func (api objectAPIHandlers) GetBucketPolicyHandler(w http.ResponseWriter, r *ht
objAPI := api.ObjectAPI() objAPI := api.ObjectAPI()
if objAPI == nil { if objAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
@ -153,26 +153,26 @@ func (api objectAPIHandlers) GetBucketPolicyHandler(w http.ResponseWriter, r *ht
bucket := vars["bucket"] bucket := vars["bucket"]
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Check if bucket exists. // Check if bucket exists.
if _, err := objAPI.GetBucketInfo(ctx, bucket); err != nil { if _, err := objAPI.GetBucketInfo(ctx, bucket); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
// Read bucket access policy. // Read bucket access policy.
bucketPolicy, err := objAPI.GetBucketPolicy(ctx, bucket) bucketPolicy, err := objAPI.GetBucketPolicy(ctx, bucket)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
policyData, err := json.Marshal(bucketPolicy) policyData, err := json.Marshal(bucketPolicy)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }

View File

@ -17,21 +17,22 @@
package cmd package cmd
import ( import (
"context"
"net/http" "net/http"
"net/url" "net/url"
) )
// Writes S3 compatible copy part range error. // Writes S3 compatible copy part range error.
func writeCopyPartErr(w http.ResponseWriter, err error, url *url.URL, browser bool) { func writeCopyPartErr(ctx context.Context, w http.ResponseWriter, err error, url *url.URL, browser bool) {
switch err { switch err {
case errInvalidRange: case errInvalidRange:
writeErrorResponse(w, ErrInvalidCopyPartRange, url, browser) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInvalidCopyPartRange), url, browser)
return return
case errInvalidRangeSource: case errInvalidRangeSource:
writeErrorResponse(w, ErrInvalidCopyPartRangeSource, url, browser) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInvalidCopyPartRangeSource), url, browser)
return return
default: default:
writeErrorResponse(w, ErrInternalError, url, browser) writeErrorResponse(w, toAPIError(ctx, err), url, browser)
return return
} }
} }

View File

@ -129,27 +129,27 @@ func (api objectAPIHandlers) GetBucketCorsHandler(w http.ResponseWriter, r *http
objAPI := api.ObjectAPI() objAPI := api.ObjectAPI()
if objAPI == nil { if objAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
// Allow getBucketCors if policy action is set, since this is a dummy call // Allow getBucketCors if policy action is set, since this is a dummy call
// we are simply re-purposing the bucketPolicyAction. // we are simply re-purposing the bucketPolicyAction.
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Validate if bucket exists, before proceeding further... // Validate if bucket exists, before proceeding further...
_, err := objAPI.GetBucketInfo(ctx, bucket) _, err := objAPI.GetBucketInfo(ctx, bucket)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
cors := &corsConfiguration{} cors := &corsConfiguration{}
if err := xml.NewEncoder(w).Encode(cors); err != nil { if err := xml.NewEncoder(w).Encode(cors); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -165,21 +165,21 @@ func (api objectAPIHandlers) GetBucketTaggingHandler(w http.ResponseWriter, r *h
objAPI := api.ObjectAPI() objAPI := api.ObjectAPI()
if objAPI == nil { if objAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
// Allow getBucketTagging if policy action is set, since this is a dummy call // Allow getBucketTagging if policy action is set, since this is a dummy call
// we are simply re-purposing the bucketPolicyAction. // we are simply re-purposing the bucketPolicyAction.
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Validate if bucket exists, before proceeding further... // Validate if bucket exists, before proceeding further...
_, err := objAPI.GetBucketInfo(ctx, bucket) _, err := objAPI.GetBucketInfo(ctx, bucket)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -187,7 +187,7 @@ func (api objectAPIHandlers) GetBucketTaggingHandler(w http.ResponseWriter, r *h
tags.TagSet.Tag = append(tags.TagSet.Tag, tagElem{}) tags.TagSet.Tag = append(tags.TagSet.Tag, tagElem{})
if err := xml.NewEncoder(w).Encode(tags); err != nil { if err := xml.NewEncoder(w).Encode(tags); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -204,21 +204,21 @@ func (api objectAPIHandlers) GetObjectTaggingHandler(w http.ResponseWriter, r *h
objAPI := api.ObjectAPI() objAPI := api.ObjectAPI()
if objAPI == nil { if objAPI == nil {
writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
return return
} }
// Allow getObjectTagging if policy action is set, since this is a dummy call // Allow getObjectTagging if policy action is set, since this is a dummy call
// we are simply re-purposing the bucketPolicyAction. // we are simply re-purposing the bucketPolicyAction.
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone {
writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
// Validate if object exists, before proceeding further... // Validate if object exists, before proceeding further...
_, err := objAPI.GetObjectInfo(ctx, bucket, object, ObjectOptions{}) _, err := objAPI.GetObjectInfo(ctx, bucket, object, ObjectOptions{})
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -226,7 +226,7 @@ func (api objectAPIHandlers) GetObjectTaggingHandler(w http.ResponseWriter, r *h
tags.TagSet.Tag = append(tags.TagSet.Tag, tagElem{}) tags.TagSet.Tag = append(tags.TagSet.Tag, tagElem{})
if err := xml.NewEncoder(w).Encode(tags); err != nil { if err := xml.NewEncoder(w).Encode(tags); err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }

View File

@ -1103,22 +1103,22 @@ func (o *ObjectInfo) EncryptedSize() int64 {
// decryption succeeded. // decryption succeeded.
// //
// DecryptCopyObjectInfo also returns whether the object is encrypted or not. // DecryptCopyObjectInfo also returns whether the object is encrypted or not.
func DecryptCopyObjectInfo(info *ObjectInfo, headers http.Header) (apiErr APIErrorCode, encrypted bool) { func DecryptCopyObjectInfo(info *ObjectInfo, headers http.Header) (errCode APIErrorCode, encrypted bool) {
// Directories are never encrypted. // Directories are never encrypted.
if info.IsDir { if info.IsDir {
return ErrNone, false return ErrNone, false
} }
if apiErr, encrypted = ErrNone, crypto.IsEncrypted(info.UserDefined); !encrypted && crypto.SSECopy.IsRequested(headers) { if errCode, encrypted = ErrNone, crypto.IsEncrypted(info.UserDefined); !encrypted && crypto.SSECopy.IsRequested(headers) {
apiErr = ErrInvalidEncryptionParameters errCode = ErrInvalidEncryptionParameters
} else if encrypted { } else if encrypted {
if (!crypto.SSECopy.IsRequested(headers) && crypto.SSEC.IsEncrypted(info.UserDefined)) || if (!crypto.SSECopy.IsRequested(headers) && crypto.SSEC.IsEncrypted(info.UserDefined)) ||
(crypto.SSECopy.IsRequested(headers) && crypto.S3.IsEncrypted(info.UserDefined)) { (crypto.SSECopy.IsRequested(headers) && crypto.S3.IsEncrypted(info.UserDefined)) {
apiErr = ErrSSEEncryptedObject errCode = ErrSSEEncryptedObject
return return
} }
var err error var err error
if info.Size, err = info.DecryptedSize(); err != nil { if info.Size, err = info.DecryptedSize(); err != nil {
apiErr = toAPIErrorCode(context.Background(), err) errCode = toAPIErrorCode(context.Background(), err)
} }
} }
return return

View File

@ -324,8 +324,6 @@ func gcsToObjectError(err error, params ...string) error {
break break
} }
err = minio.BucketNotEmpty{Bucket: bucket} err = minio.BucketNotEmpty{Bucket: bucket}
default:
err = fmt.Errorf("Unsupported error reason: %s", reason)
} }
return err return err

View File

@ -375,15 +375,6 @@ func TestGCSToObjectError(t *testing.T) {
Object: "object", Object: "object",
}, },
}, },
{
[]string{"bucket", "object"},
&googleapi.Error{
Errors: []googleapi.ErrorItem{{
Reason: "unknown",
}},
},
fmt.Errorf("Unsupported error reason: unknown"),
},
} }
for i, testCase := range testCases { for i, testCase := range testCases {

View File

@ -90,7 +90,7 @@ func setRequestHeaderSizeLimitHandler(h http.Handler) http.Handler {
// of the user-defined metadata to 2 KB. // of the user-defined metadata to 2 KB.
func (h requestHeaderSizeLimitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h requestHeaderSizeLimitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if isHTTPHeaderSizeTooLarge(r.Header) { if isHTTPHeaderSizeTooLarge(r.Header) {
writeErrorResponse(w, ErrMetadataTooLarge, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMetadataTooLarge), r.URL, guessIsBrowserReq(r))
return return
} }
h.Handler.ServeHTTP(w, r) h.Handler.ServeHTTP(w, r)
@ -133,7 +133,7 @@ func filterReservedMetadata(h http.Handler) http.Handler {
// would be treated as metadata. // would be treated as metadata.
func (h reservedMetadataHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h reservedMetadataHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if containsReservedMetadata(r.Header) { if containsReservedMetadata(r.Header) {
writeErrorResponse(w, ErrUnsupportedMetadata, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrUnsupportedMetadata), r.URL, guessIsBrowserReq(r))
return return
} }
h.Handler.ServeHTTP(w, r) h.Handler.ServeHTTP(w, r)
@ -300,7 +300,7 @@ func (h minioReservedBucketHandler) ServeHTTP(w http.ResponseWriter, r *http.Req
// buckets // buckets
bucketName, _ := urlPath2BucketObjectName(r.URL.Path) bucketName, _ := urlPath2BucketObjectName(r.URL.Path)
if isMinioReservedBucket(bucketName) || isMinioMetaBucket(bucketName) { if isMinioReservedBucket(bucketName) || isMinioMetaBucket(bucketName) {
writeErrorResponse(w, ErrAllAccessDisabled, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrAllAccessDisabled), r.URL, guessIsBrowserReq(r))
return return
} }
} }
@ -358,19 +358,19 @@ func (h timeValidityHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
aType := getRequestAuthType(r) aType := getRequestAuthType(r)
if aType == authTypeSigned || aType == authTypeSignedV2 || aType == authTypeStreamingSigned { if aType == authTypeSigned || aType == authTypeSignedV2 || aType == authTypeStreamingSigned {
// Verify if date headers are set, if not reject the request // Verify if date headers are set, if not reject the request
amzDate, apiErr := parseAmzDateHeader(r) amzDate, errCode := parseAmzDateHeader(r)
if apiErr != ErrNone { if errCode != ErrNone {
// 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, apiErr, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(errCode), r.URL, guessIsBrowserReq(r))
return return
} }
// Verify if the request date header is shifted by less than globalMaxSkewTime parameter in the past // Verify if the request date header is shifted by less than globalMaxSkewTime parameter in the past
// or in the future, reject request otherwise. // or in the future, reject request otherwise.
curTime := UTCNow() curTime := UTCNow()
if curTime.Sub(amzDate) > globalMaxSkewTime || amzDate.Sub(curTime) > globalMaxSkewTime { if curTime.Sub(amzDate) > globalMaxSkewTime || amzDate.Sub(curTime) > globalMaxSkewTime {
writeErrorResponse(w, ErrRequestTimeTooSkewed, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrRequestTimeTooSkewed), r.URL, guessIsBrowserReq(r))
return return
} }
} }
@ -473,14 +473,14 @@ func (h resourceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// If bucketName is present and not objectName check for bucket level resource queries. // If bucketName is present and not objectName check for bucket level resource queries.
if bucketName != "" && objectName == "" { if bucketName != "" && objectName == "" {
if ignoreNotImplementedBucketResources(r) { if ignoreNotImplementedBucketResources(r) {
writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
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, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
return return
} }
} }
@ -584,14 +584,14 @@ func hasBadPathComponent(path string) bool {
func (h pathValidityHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h pathValidityHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Check for bad components in URL path. // Check for bad components in URL path.
if hasBadPathComponent(r.URL.Path) { if hasBadPathComponent(r.URL.Path) {
writeErrorResponse(w, ErrInvalidResourceName, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInvalidResourceName), r.URL, guessIsBrowserReq(r))
return return
} }
// Check for bad components in URL query values. // Check for bad components in URL query values.
for _, vv := range r.URL.Query() { for _, vv := range r.URL.Query() {
for _, v := range vv { for _, v := range vv {
if hasBadPathComponent(v) { if hasBadPathComponent(v) {
writeErrorResponse(w, ErrInvalidResourceName, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInvalidResourceName), r.URL, guessIsBrowserReq(r))
return return
} }
} }
@ -635,9 +635,9 @@ func (f bucketForwardingHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
sr, err := globalDNSConfig.Get(bucket) sr, err := globalDNSConfig.Get(bucket)
if err != nil { if err != nil {
if err == dns.ErrNoEntriesFound { if err == dns.ErrNoEntriesFound {
writeErrorResponse(w, ErrNoSuchBucket, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNoSuchBucket), r.URL, guessIsBrowserReq(r))
} else { } else {
writeErrorResponse(w, toAPIErrorCode(context.Background(), err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(context.Background(), err), r.URL, guessIsBrowserReq(r))
} }
return return
} }
@ -679,9 +679,9 @@ func (f bucketForwardingHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
sr, err := globalDNSConfig.Get(bucket) sr, err := globalDNSConfig.Get(bucket)
if err != nil { if err != nil {
if err == dns.ErrNoEntriesFound { if err == dns.ErrNoEntriesFound {
writeErrorResponse(w, ErrNoSuchBucket, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrNoSuchBucket), r.URL, guessIsBrowserReq(r))
} else { } else {
writeErrorResponse(w, toAPIErrorCode(context.Background(), err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(context.Background(), err), r.URL, guessIsBrowserReq(r))
} }
return return
} }
@ -741,7 +741,7 @@ func (l rateLimit) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// potential pileup on the server. // potential pileup on the server.
if err := l.Wait(ctx); err != nil { if err := l.Wait(ctx); err != nil {
// Send an S3 compatible error, SlowDown. // Send an S3 compatible error, SlowDown.
writeErrorResponse(w, ErrSlowDown, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrSlowDown), r.URL, guessIsBrowserReq(r))
return return
} }
@ -795,7 +795,7 @@ type criticalErrorHandler struct{ handler http.Handler }
func (h criticalErrorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h criticalErrorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer func() { defer func() {
if err := recover(); err == logger.ErrCritical { // handle if err := recover(); err == logger.ErrCritical { // handle
writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInternalError), r.URL, guessIsBrowserReq(r))
} else if err != nil { } else if err != nil {
panic(err) // forward other panic calls panic(err) // forward other panic calls
} }
@ -812,9 +812,9 @@ func (h sseTLSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Deny SSE-C requests if not made over TLS // Deny SSE-C requests if not made over TLS
if !globalIsSSL && (crypto.SSEC.IsRequested(r.Header) || crypto.SSECopy.IsRequested(r.Header)) { if !globalIsSSL && (crypto.SSEC.IsRequested(r.Header) || crypto.SSECopy.IsRequested(r.Header)) {
if r.Method == http.MethodHead { if r.Method == http.MethodHead {
writeErrorResponseHeadersOnly(w, ErrInsecureSSECustomerRequest) writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(ErrInsecureSSECustomerRequest))
} else { } else {
writeErrorResponse(w, ErrInsecureSSECustomerRequest, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrInsecureSSECustomerRequest), r.URL, guessIsBrowserReq(r))
} }
return return
} }

View File

@ -366,12 +366,12 @@ func getResource(path string, host string, domain string) (string, error) {
// If none of the http routes match respond with MethodNotAllowed, in JSON // If none of the http routes match respond with MethodNotAllowed, in JSON
func notFoundHandlerJSON(w http.ResponseWriter, r *http.Request) { func notFoundHandlerJSON(w http.ResponseWriter, r *http.Request) {
writeErrorResponseJSON(w, ErrMethodNotAllowed, r.URL) writeErrorResponseJSON(w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL)
return return
} }
// If none of the http routes match respond with MethodNotAllowed // If none of the http routes match respond with MethodNotAllowed
func notFoundHandler(w http.ResponseWriter, r *http.Request) { func notFoundHandler(w http.ResponseWriter, r *http.Request) {
writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL, guessIsBrowserReq(r))
return return
} }

View File

@ -75,7 +75,7 @@ func checkCopyObjectPreconditions(w http.ResponseWriter, r *http.Request, objInf
if !ifModifiedSince(objInfo.ModTime, givenTime) { if !ifModifiedSince(objInfo.ModTime, givenTime) {
// If the object is not modified since the specified time. // If the object is not modified since the specified time.
writeHeaders() writeHeaders()
writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrPreconditionFailed), r.URL, guessIsBrowserReq(r))
return true return true
} }
} }
@ -89,7 +89,7 @@ func checkCopyObjectPreconditions(w http.ResponseWriter, r *http.Request, objInf
if ifModifiedSince(objInfo.ModTime, givenTime) { if ifModifiedSince(objInfo.ModTime, givenTime) {
// If the object is modified since the specified time. // If the object is modified since the specified time.
writeHeaders() writeHeaders()
writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrPreconditionFailed), r.URL, guessIsBrowserReq(r))
return true return true
} }
} }
@ -102,7 +102,7 @@ func checkCopyObjectPreconditions(w http.ResponseWriter, r *http.Request, objInf
if objInfo.ETag != "" && !isETagEqual(objInfo.ETag, ifMatchETagHeader) { if objInfo.ETag != "" && !isETagEqual(objInfo.ETag, ifMatchETagHeader) {
// If the object ETag does not match with the specified ETag. // If the object ETag does not match with the specified ETag.
writeHeaders() writeHeaders()
writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrPreconditionFailed), r.URL, guessIsBrowserReq(r))
return true return true
} }
} }
@ -114,7 +114,7 @@ func checkCopyObjectPreconditions(w http.ResponseWriter, r *http.Request, objInf
if objInfo.ETag != "" && isETagEqual(objInfo.ETag, ifNoneMatchETagHeader) { if objInfo.ETag != "" && isETagEqual(objInfo.ETag, ifNoneMatchETagHeader) {
// If the object ETag matches with the specified ETag. // If the object ETag matches with the specified ETag.
writeHeaders() writeHeaders()
writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrPreconditionFailed), r.URL, guessIsBrowserReq(r))
return true return true
} }
} }
@ -174,7 +174,7 @@ func checkPreconditions(w http.ResponseWriter, r *http.Request, objInfo ObjectIn
if ifModifiedSince(objInfo.ModTime, givenTime) { if ifModifiedSince(objInfo.ModTime, givenTime) {
// If the object is modified since the specified time. // If the object is modified since the specified time.
writeHeaders() writeHeaders()
writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrPreconditionFailed), r.URL, guessIsBrowserReq(r))
return true return true
} }
} }
@ -187,7 +187,7 @@ func checkPreconditions(w http.ResponseWriter, r *http.Request, objInfo ObjectIn
if !isETagEqual(objInfo.ETag, ifMatchETagHeader) { if !isETagEqual(objInfo.ETag, ifMatchETagHeader) {
// If the object ETag does not match with the specified ETag. // If the object ETag does not match with the specified ETag.
writeHeaders() writeHeaders()
writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, errorCodes.ToAPIErr(ErrPreconditionFailed), r.URL, guessIsBrowserReq(r))
return true return true
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -2640,7 +2640,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
accessKey: credentials.AccessKey, accessKey: credentials.AccessKey,
secretKey: credentials.SecretKey, secretKey: credentials.SecretKey,
expectedContent: encodeResponse(getAPIErrorResponse(getAPIError(toAPIErrorCode(ctx, InvalidPart{})), expectedContent: encodeResponse(getAPIErrorResponse(toAPIError(ctx, InvalidPart{}),
getGetObjectURL("", bucketName, objectName), "")), getGetObjectURL("", bucketName, objectName), "")),
expectedRespStatus: http.StatusBadRequest, expectedRespStatus: http.StatusBadRequest,
}, },
@ -2670,7 +2670,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
accessKey: credentials.AccessKey, accessKey: credentials.AccessKey,
secretKey: credentials.SecretKey, secretKey: credentials.SecretKey,
expectedContent: encodeResponse(getAPIErrorResponse(getAPIError(toAPIErrorCode(ctx, InvalidUploadID{UploadID: "abc"})), expectedContent: encodeResponse(getAPIErrorResponse(toAPIError(ctx, InvalidUploadID{UploadID: "abc"}),
getGetObjectURL("", bucketName, objectName), "")), getGetObjectURL("", bucketName, objectName), "")),
expectedRespStatus: http.StatusNotFound, expectedRespStatus: http.StatusNotFound,
}, },
@ -2685,7 +2685,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
secretKey: credentials.SecretKey, secretKey: credentials.SecretKey,
expectedContent: encodeResponse(completeMultipartAPIError{int64(4), int64(5242880), 1, "e2fc714c4727ee9395f324cd2e7f331f", expectedContent: encodeResponse(completeMultipartAPIError{int64(4), int64(5242880), 1, "e2fc714c4727ee9395f324cd2e7f331f",
getAPIErrorResponse(getAPIError(toAPIErrorCode(ctx, PartTooSmall{PartNumber: 1})), getAPIErrorResponse(toAPIError(ctx, PartTooSmall{PartNumber: 1}),
getGetObjectURL("", bucketName, objectName), "")}), getGetObjectURL("", bucketName, objectName), "")}),
expectedRespStatus: http.StatusBadRequest, expectedRespStatus: http.StatusBadRequest,
}, },
@ -2699,7 +2699,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
accessKey: credentials.AccessKey, accessKey: credentials.AccessKey,
secretKey: credentials.SecretKey, secretKey: credentials.SecretKey,
expectedContent: encodeResponse(getAPIErrorResponse(getAPIError(toAPIErrorCode(ctx, InvalidPart{})), expectedContent: encodeResponse(getAPIErrorResponse(toAPIError(ctx, InvalidPart{}),
getGetObjectURL("", bucketName, objectName), "")), getGetObjectURL("", bucketName, objectName), "")),
expectedRespStatus: http.StatusBadRequest, expectedRespStatus: http.StatusBadRequest,
}, },

View File

@ -222,7 +222,7 @@ func TestParseCredentialHeader(t *testing.T) {
actualCredential, actualErrCode := parseCredentialHeader(testCase.inputCredentialStr, "us-west-1") actualCredential, actualErrCode := parseCredentialHeader(testCase.inputCredentialStr, "us-west-1")
// validating the credential fields. // validating the credential fields.
if testCase.expectedErrCode != actualErrCode { if testCase.expectedErrCode != actualErrCode {
t.Fatalf("Test %d: Expected the APIErrCode to be %s, got %s", i+1, errorCodeResponse[testCase.expectedErrCode].Code, errorCodeResponse[actualErrCode].Code) t.Fatalf("Test %d: Expected the APIErrCode to be %s, got %s", i+1, errorCodes[testCase.expectedErrCode].Code, errorCodes[actualErrCode].Code)
} }
if actualErrCode == ErrNone { if actualErrCode == ErrNone {
validateCredentialfields(t, i+1, testCase.expectedCredentials, actualCredential) validateCredentialfields(t, i+1, testCase.expectedCredentials, actualCredential)

View File

@ -31,7 +31,7 @@ func niceError(code APIErrorCode) string {
return "ErrNone" return "ErrNone"
} }
return fmt.Sprintf("%s (%s)", errorCodeResponse[code].Code, errorCodeResponse[code].Description) return fmt.Sprintf("%s (%s)", errorCodes[code].Code, errorCodes[code].Description)
} }
func TestDoesPolicySignatureMatch(t *testing.T) { func TestDoesPolicySignatureMatch(t *testing.T) {

View File

@ -2357,8 +2357,8 @@ func TestToErrIsNil(t *testing.T) {
t.Errorf("Test expected to return nil, failed instead got a non-nil value %s", toStorageErr(nil)) t.Errorf("Test expected to return nil, failed instead got a non-nil value %s", toStorageErr(nil))
} }
ctx := context.Background() ctx := context.Background()
if toAPIErrorCode(ctx, nil) != ErrNone { if toAPIError(ctx, nil) != noError {
t.Errorf("Test expected error code to be ErrNone, failed instead provided %d", toAPIErrorCode(ctx, nil)) t.Errorf("Test expected error code to be ErrNone, failed instead provided %s", toAPIError(ctx, nil).Code)
} }
} }

View File

@ -894,7 +894,7 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
// Extract incoming metadata if any. // Extract incoming metadata if any.
metadata, err := extractMetadata(context.Background(), r) metadata, err := extractMetadata(context.Background(), r)
if err != nil { if err != nil {
writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
@ -943,7 +943,7 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
var opts ObjectOptions var opts ObjectOptions
opts, err = putOpts(ctx, r, bucket, object, metadata) opts, err = putOpts(ctx, r, bucket, object, metadata)
if err != nil { if err != nil {
writeErrorResponseHeadersOnly(w, toAPIErrorCode(ctx, err)) writeErrorResponseHeadersOnly(w, toAPIError(ctx, err))
return return
} }
if objectAPI.IsEncryptionSupported() { if objectAPI.IsEncryptionSupported() {
@ -952,13 +952,13 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
var objectEncryptionKey []byte var objectEncryptionKey []byte
reader, objectEncryptionKey, err = EncryptRequest(hashReader, r, bucket, object, metadata) reader, objectEncryptionKey, err = EncryptRequest(hashReader, r, bucket, object, metadata)
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
info := ObjectInfo{Size: size} info := ObjectInfo{Size: size}
hashReader, err = hash.NewReader(reader, info.EncryptedSize(), "", "", size) // do not try to verify encrypted content hashReader, err = hash.NewReader(reader, info.EncryptedSize(), "", "", size) // do not try to verify encrypted content
if err != nil { if err != nil {
writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) writeErrorResponse(w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return return
} }
pReader = NewPutObjReader(rawReader, hashReader, objectEncryptionKey) pReader = NewPutObjReader(rawReader, hashReader, objectEncryptionKey)