diff --git a/cmd/acl-handlers.go b/cmd/acl-handlers.go index 2fad04ad0..f96be62f0 100644 --- a/cmd/acl-handlers.go +++ b/cmd/acl-handlers.go @@ -64,21 +64,21 @@ func (api objectAPIHandlers) GetBucketACLHandler(w http.ResponseWriter, r *http. objAPI := api.ObjectAPI() if objAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } // Allow getBucketACL if policy action is set, since this is a dummy call // we are simply re-purposing the bucketPolicyAction. if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Before proceeding validate if bucket exists. _, err := objAPI.GetBucketInfo(ctx, bucket) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -92,7 +92,7 @@ func (api objectAPIHandlers) GetBucketACLHandler(w http.ResponseWriter, r *http. Permission: "FULL_CONTROL", }) if err := xml.NewEncoder(w).Encode(acl); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -114,21 +114,21 @@ func (api objectAPIHandlers) GetObjectACLHandler(w http.ResponseWriter, r *http. objAPI := api.ObjectAPI() if objAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } // Allow getObjectACL if policy action is set, since this is a dummy call // we are simply re-purposing the bucketPolicyAction. if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Before proceeding validate if object exists. _, err := objAPI.GetObjectInfo(ctx, bucket, object, ObjectOptions{}) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -142,7 +142,7 @@ func (api objectAPIHandlers) GetObjectACLHandler(w http.ResponseWriter, r *http. Permission: "FULL_CONTROL", }) if err := xml.NewEncoder(w).Encode(acl); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index f4538694b..e0d2e037a 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -578,7 +578,7 @@ func (a adminAPIHandlers) HealHandler(w http.ResponseWriter, r *http.Request) { StartTime: nh.startTime, }) if err != nil { - writeErrorResponse(w, toAdminAPIErrCode(ctx, err), r.URL) + writeErrorResponseJSON(w, toAdminAPIErrCode(ctx, err), r.URL) return } // Client token not specified but a heal sequence exists on a path, @@ -859,7 +859,7 @@ func (a adminAPIHandlers) SetUserStatus(w http.ResponseWriter, r *http.Request) // Custom IAM policies not allowed for admin user. if accessKey == globalServerConfig.GetCredential().AccessKey { - writeErrorResponse(w, ErrInvalidRequest, r.URL) + writeErrorResponseJSON(w, ErrInvalidRequest, r.URL) return } @@ -898,7 +898,7 @@ func (a adminAPIHandlers) AddUser(w http.ResponseWriter, r *http.Request) { // Custom IAM policies not allowed for admin user. if accessKey == globalServerConfig.GetCredential().AccessKey { - writeErrorResponse(w, ErrInvalidRequest, r.URL) + writeErrorResponseJSON(w, ErrInvalidRequest, r.URL) return } diff --git a/cmd/api-response.go b/cmd/api-response.go index 7efc7ec86..68ec85b98 100644 --- a/cmd/api-response.go +++ b/cmd/api-response.go @@ -568,13 +568,20 @@ func writeSuccessResponseHeadersOnly(w http.ResponseWriter) { } // writeErrorRespone writes error headers -func writeErrorResponse(w http.ResponseWriter, errorCode APIErrorCode, reqURL *url.URL) { +func writeErrorResponse(w http.ResponseWriter, errorCode APIErrorCode, reqURL *url.URL, browser bool) { switch errorCode { case ErrSlowDown, ErrServerNotInitialized, ErrReadQuorum, ErrWriteQuorum: // 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 w.Header().Set("Retry-After", "120") + case ErrAccessDenied: + if browser { + w.Header().Set("Location", minioReservedBucketPath+reqURL.Path) + w.WriteHeader(http.StatusTemporaryRedirect) + return + } } + apiError := getAPIError(errorCode) // Generate error response. errorResponse := getAPIErrorResponse(apiError, reqURL.Path, w.Header().Get(responseRequestIDKey)) diff --git a/cmd/auth-handler.go b/cmd/auth-handler.go index f9ccf2776..3af7f21b0 100644 --- a/cmd/auth-handler.go +++ b/cmd/auth-handler.go @@ -419,7 +419,7 @@ func (a authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { a.handler.ServeHTTP(w, r) return } - writeErrorResponse(w, ErrSignatureVersionNotSupported, r.URL) + writeErrorResponse(w, ErrSignatureVersionNotSupported, r.URL, guessIsBrowserReq(r)) } // isPutAllowed - check if PUT operation is allowed on the resource, this diff --git a/cmd/bucket-handlers-listobjects.go b/cmd/bucket-handlers-listobjects.go index 2bf798ede..f90258ba3 100644 --- a/cmd/bucket-handlers-listobjects.go +++ b/cmd/bucket-handlers-listobjects.go @@ -66,12 +66,12 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -81,14 +81,14 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http prefix, token, startAfter, delimiter, fetchOwner, maxKeys, _, errCode := getListObjectsV2Args(urlValues) if errCode != ErrNone { - writeErrorResponse(w, errCode, r.URL) + writeErrorResponse(w, errCode, r.URL, guessIsBrowserReq(r)) return } // Validate the query params before beginning to serve the request. // fetch-owner is not validated since it is a boolean if s3Error := validateListObjectsArgs(prefix, token, delimiter, maxKeys); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } listObjectsV2 := objectAPI.ListObjectsV2 @@ -100,7 +100,7 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http // marshaled into S3 compatible XML header. listObjectsV2Info, err := listObjectsV2(ctx, bucket, prefix, token, delimiter, maxKeys, fetchOwner, startAfter) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -110,7 +110,7 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http // Read the decompressed size from the meta.json. actualSize = listObjectsV2Info.Objects[i].GetActualSize() if actualSize < 0 { - writeErrorResponse(w, ErrInvalidDecompressedSize, r.URL) + writeErrorResponse(w, ErrInvalidDecompressedSize, r.URL, guessIsBrowserReq(r)) return } // 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].Size, err = listObjectsV2Info.Objects[i].DecryptedSize() if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -148,30 +148,30 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Extract all the litsObjectsV1 query params to their native values. prefix, marker, delimiter, maxKeys, _, s3Error := getListObjectsV1Args(r.URL.Query()) if s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Validate the maxKeys lowerbound. When maxKeys > 1000, S3 returns 1000 but // does not throw an error. if maxKeys < 0 { - writeErrorResponse(w, ErrInvalidMaxKeys, r.URL) + 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 { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } listObjects := objectAPI.ListObjects @@ -183,7 +183,7 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http // marshaled into S3 compatible XML header. listObjectsInfo, err := listObjects(ctx, bucket, prefix, marker, delimiter, maxKeys) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -193,7 +193,7 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http // Read the decompressed size from the meta.json. actualSize = listObjectsInfo.Objects[i].GetActualSize() if actualSize < 0 { - writeErrorResponse(w, ErrInvalidDecompressedSize, r.URL) + writeErrorResponse(w, ErrInvalidDecompressedSize, r.URL, guessIsBrowserReq(r)) return } // Set the info.Size to the actualSize. @@ -202,7 +202,7 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http listObjectsInfo.Objects[i].ETag = getDecryptedETag(r.Header, listObjectsInfo.Objects[i], false) listObjectsInfo.Objects[i].Size, err = listObjectsInfo.Objects[i].DecryptedSize() if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index f4c67b3ec..addc5cf30 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -96,12 +96,12 @@ func (api objectAPIHandlers) GetBucketLocationHandler(w http.ResponseWriter, r * objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketLocationAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -110,7 +110,7 @@ func (api objectAPIHandlers) GetBucketLocationHandler(w http.ResponseWriter, r * getBucketInfo = api.CacheAPI().GetBucketInfo } if _, err := getBucketInfo(ctx, bucket); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -146,35 +146,35 @@ func (api objectAPIHandlers) ListMultipartUploadsHandler(w http.ResponseWriter, objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketMultipartUploadsAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } prefix, keyMarker, uploadIDMarker, delimiter, maxUploads, _, s3Error := getBucketMultipartResources(r.URL.Query()) if s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } if maxUploads < 0 { - writeErrorResponse(w, ErrInvalidMaxUploads, r.URL) + writeErrorResponse(w, ErrInvalidMaxUploads, r.URL, guessIsBrowserReq(r)) return } if keyMarker != "" { // Marker not common with prefix is not implemented. if !hasPrefix(keyMarker, prefix) { - writeErrorResponse(w, ErrNotImplemented, r.URL) + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) return } } listMultipartsInfo, err := objectAPI.ListMultipartUploads(ctx, bucket, prefix, keyMarker, uploadIDMarker, delimiter, maxUploads) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } // generate response @@ -196,7 +196,7 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } listBuckets := objectAPI.ListBuckets @@ -206,7 +206,7 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R } if s3Error := checkRequestAuthType(ctx, r, policy.ListAllMyBucketsAction, "", ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // If etcd, dns federation configured list buckets from etcd. @@ -214,7 +214,7 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R if globalDNSConfig != nil { dnsBuckets, err := globalDNSConfig.List() if err != nil && err != dns.ErrNoEntriesFound { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } bucketSet := set.NewStringSet() @@ -233,7 +233,7 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R var err error bucketsInfo, err = listBuckets(ctx) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -257,7 +257,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } @@ -266,7 +266,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, // In the event access is denied, a 200 response should still be returned // http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html if s3Error != ErrAccessDenied { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } } @@ -274,14 +274,14 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, // Content-Length is required and should be non-zero // http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html if r.ContentLength <= 0 { - writeErrorResponse(w, ErrMissingContentLength, r.URL) + writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) return } // Content-Md5 is requied should be set // http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html if _, ok := r.Header["Content-Md5"]; !ok { - writeErrorResponse(w, ErrMissingContentMD5, r.URL) + writeErrorResponse(w, ErrMissingContentMD5, r.URL, guessIsBrowserReq(r)) return } @@ -297,7 +297,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, // Read incoming body XML bytes. if _, err := io.ReadFull(r.Body, deleteXMLBytes); err != nil { logger.LogIf(ctx, err) - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) return } @@ -305,7 +305,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, deleteObjects := &DeleteObjectsRequest{} if err := xml.Unmarshal(deleteXMLBytes, deleteObjects); err != nil { logger.LogIf(ctx, err) - writeErrorResponse(w, ErrMalformedXML, r.URL) + writeErrorResponse(w, ErrMalformedXML, r.URL, guessIsBrowserReq(r)) return } @@ -313,7 +313,7 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, if globalWORMEnabled { // Not required to check whether given objects exist or not, because // DeleteMultipleObject is always successful irrespective of object existence. - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } @@ -401,7 +401,7 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } @@ -409,21 +409,21 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req bucket := vars["bucket"] if s3Error := checkRequestAuthType(ctx, r, policy.CreateBucketAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Parse incoming location constraint. location, s3Error := parseLocationConstraint(r) if s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Validate if location sent by the client is valid, reject // requests which do not follow valid region requirements. if !isValidLocation(location) { - writeErrorResponse(w, ErrInvalidRegion, r.URL) + writeErrorResponse(w, ErrInvalidRegion, r.URL, guessIsBrowserReq(r)) return } @@ -432,12 +432,12 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req if err == dns.ErrNoEntriesFound { // Proceed to creating a bucket. if err = objectAPI.MakeBucketWithLocation(ctx, bucket, location); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } if err = globalDNSConfig.Put(bucket); err != nil { objectAPI.DeleteBucket(ctx, bucket) - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -447,18 +447,18 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req writeSuccessResponseHeadersOnly(w) return } - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } - writeErrorResponse(w, ErrBucketAlreadyOwnedByYou, r.URL) + writeErrorResponse(w, ErrBucketAlreadyOwnedByYou, r.URL, guessIsBrowserReq(r)) return } // Proceed to creating a bucket. err := objectAPI.MakeBucketWithLocation(ctx, bucket, location) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -479,7 +479,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } @@ -488,17 +488,17 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h // Require Content-Length to be set in the request size := r.ContentLength if size < 0 { - writeErrorResponse(w, ErrMissingContentLength, r.URL) + writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) return } resource, err := getResource(r.URL.Path, r.Host, globalDomainName) if err != nil { - writeErrorResponse(w, ErrInvalidRequest, r.URL) + writeErrorResponse(w, ErrInvalidRequest, r.URL, guessIsBrowserReq(r)) return } // Make sure that the URL does not contain object name. if bucket != filepath.Clean(resource[1:]) { - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } @@ -507,7 +507,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h reader, err := r.MultipartReader() if err != nil { logger.LogIf(ctx, err) - writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) + writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) return } @@ -515,7 +515,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h form, err := reader.ReadForm(maxFormMemory) if err != nil { logger.LogIf(ctx, err) - writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) + writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) return } @@ -526,13 +526,13 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h fileBody, fileName, fileSize, formValues, err := extractPostPolicyFormValues(ctx, form) if err != nil { logger.LogIf(ctx, err) - writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) + writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) return } // Check if file is provided, error out otherwise. if fileBody == nil { - writeErrorResponse(w, ErrPOSTFileRequired, r.URL) + writeErrorResponse(w, ErrPOSTFileRequired, r.URL, guessIsBrowserReq(r)) return } @@ -554,7 +554,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h if successRedirect != "" { redirectURL, err = url.Parse(successRedirect) if err != nil { - writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) + writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) return } } @@ -562,25 +562,25 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h // Verify policy signature. apiErr := doesPolicySignatureMatch(formValues) if apiErr != ErrNone { - writeErrorResponse(w, apiErr, r.URL) + writeErrorResponse(w, apiErr, r.URL, guessIsBrowserReq(r)) return } policyBytes, err := base64.StdEncoding.DecodeString(formValues.Get("Policy")) if err != nil { - writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) + writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) return } postPolicyForm, err := parsePostPolicyForm(string(policyBytes)) if err != nil { - writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) + writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL, guessIsBrowserReq(r)) return } // Make sure formValues adhere to policy restrictions. if apiErr = checkPostPolicy(formValues, postPolicyForm); apiErr != ErrNone { - writeErrorResponse(w, apiErr, r.URL) + writeErrorResponse(w, apiErr, r.URL, guessIsBrowserReq(r)) return } @@ -589,12 +589,12 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h lengthRange := postPolicyForm.Conditions.ContentLengthRange if lengthRange.Valid { if fileSize < lengthRange.Min { - writeErrorResponse(w, toAPIErrorCode(ctx, errDataTooSmall), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, errDataTooSmall), r.URL, guessIsBrowserReq(r)) return } if fileSize > lengthRange.Max || isMaxObjectSize(fileSize) { - writeErrorResponse(w, toAPIErrorCode(ctx, errDataTooLarge), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, errDataTooLarge), r.URL, guessIsBrowserReq(r)) return } } @@ -603,14 +603,14 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h metadata := make(map[string]string) err = extractMetadataFromMap(ctx, formValues, metadata) if err != nil { - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) return } hashReader, err := hash.NewReader(fileBody, fileSize, "", "", fileSize) if err != nil { logger.LogIf(ctx, err) - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } rawReader := hashReader @@ -623,19 +623,19 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h if crypto.SSEC.IsRequested(formValues) { key, err = ParseSSECustomerHeader(formValues) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } reader, objectEncryptionKey, err = newEncryptReader(hashReader, key, bucket, object, metadata, crypto.S3.IsRequested(formValues)) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } info := ObjectInfo{Size: fileSize} hashReader, err = hash.NewReader(reader, info.EncryptedSize(), "", "", fileSize) // do not try to verify encrypted content if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } pReader = NewPutObjReader(rawReader, hashReader, objectEncryptionKey) @@ -644,7 +644,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h objInfo, err := objectAPI.PutObject(ctx, bucket, object, pReader, metadata, ObjectOptions{}) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -742,12 +742,12 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http. objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.DeleteBucketAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -757,7 +757,7 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http. } // Attempt to delete bucket. if err := deleteBucket(ctx, bucket); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -769,7 +769,7 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http. if err := globalDNSConfig.Delete(bucket); err != nil { // Deleting DNS entry failed, attempt to create the bucket again. objectAPI.MakeBucketWithLocation(ctx, bucket, "") - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } diff --git a/cmd/bucket-notification-handlers.go b/cmd/bucket-notification-handlers.go index 4e88146b8..3e8738295 100644 --- a/cmd/bucket-notification-handlers.go +++ b/cmd/bucket-notification-handlers.go @@ -51,23 +51,23 @@ func (api objectAPIHandlers) GetBucketNotificationHandler(w http.ResponseWriter, objAPI := api.ObjectAPI() if objAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if !objAPI.IsNotificationSupported() { - writeErrorResponse(w, ErrNotImplemented, r.URL) + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketNotificationAction, bucketName, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } _, err := objAPI.GetBucketInfo(ctx, bucketName) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -76,7 +76,7 @@ func (api objectAPIHandlers) GetBucketNotificationHandler(w http.ResponseWriter, if err != nil { // Ignore errNoSuchNotifications to comply with AWS S3. if err != errNoSuchNotifications { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -90,7 +90,7 @@ func (api objectAPIHandlers) GetBucketNotificationHandler(w http.ResponseWriter, notificationBytes, err := xml.Marshal(nConfig) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -106,12 +106,12 @@ func (api objectAPIHandlers) PutBucketNotificationHandler(w http.ResponseWriter, objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if !objectAPI.IsNotificationSupported() { - writeErrorResponse(w, ErrNotImplemented, r.URL) + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) return } @@ -119,19 +119,19 @@ func (api objectAPIHandlers) PutBucketNotificationHandler(w http.ResponseWriter, bucketName := vars["bucket"] if s3Error := checkRequestAuthType(ctx, r, policy.PutBucketNotificationAction, bucketName, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } _, err := objectAPI.GetBucketInfo(ctx, bucketName) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } // PutBucketNotification always needs a Content-Length. if r.ContentLength <= 0 { - writeErrorResponse(w, ErrMissingContentLength, r.URL) + writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) return } @@ -143,12 +143,12 @@ func (api objectAPIHandlers) PutBucketNotificationHandler(w http.ResponseWriter, apiErr = toAPIErrorCode(ctx, err) } - writeErrorResponse(w, apiErr, r.URL) + writeErrorResponse(w, apiErr, r.URL, guessIsBrowserReq(r)) return } if err = saveNotificationConfig(ctx, objectAPI, bucketName, config); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -169,11 +169,11 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit // Validate if bucket exists. objAPI := api.ObjectAPI() if objAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if !objAPI.IsNotificationSupported() { - writeErrorResponse(w, ErrNotImplemented, r.URL) + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) return } @@ -181,7 +181,7 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit bucketName := vars["bucket"] if s3Error := checkRequestAuthType(ctx, r, policy.ListenBucketNotificationAction, bucketName, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -189,11 +189,11 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit var prefix string if len(values["prefix"]) > 1 { - writeErrorResponse(w, ErrFilterNamePrefix, r.URL) + writeErrorResponse(w, ErrFilterNamePrefix, r.URL, guessIsBrowserReq(r)) } if len(values["prefix"]) == 1 { if err := event.ValidateFilterRuleValue(values["prefix"][0]); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -202,11 +202,11 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit var suffix string if len(values["suffix"]) > 1 { - writeErrorResponse(w, ErrFilterNameSuffix, r.URL) + writeErrorResponse(w, ErrFilterNameSuffix, r.URL, guessIsBrowserReq(r)) } if len(values["suffix"]) == 1 { if err := event.ValidateFilterRuleValue(values["suffix"][0]); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -219,7 +219,7 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit for _, s := range values["events"] { eventName, err := event.ParseName(s) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -227,19 +227,19 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit } if _, err := objAPI.GetBucketInfo(ctx, bucketName); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } host, err := xnet.ParseHost(r.RemoteAddr) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } target, err := target.NewHTTPClientTarget(*host, w) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -247,7 +247,7 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit if err = globalNotificationSys.AddRemoteTarget(bucketName, target, rulesMap); err != nil { logger.GetReqInfo(ctx).AppendTags("target", target.ID().Name) - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } defer globalNotificationSys.RemoveRemoteTarget(bucketName, target.ID()) @@ -255,13 +255,13 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit thisAddr, err := xnet.ParseHost(GetLocalPeer(globalEndpoints)) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } if err = SaveListener(objAPI, bucketName, eventNames, pattern, target.ID(), *thisAddr); err != nil { logger.GetReqInfo(ctx).AppendTags("target", target.ID().Name) - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -271,7 +271,7 @@ func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWrit if err = RemoveListener(objAPI, bucketName, target.ID(), *thisAddr); err != nil { logger.GetReqInfo(ctx).AppendTags("target", target.ID().Name) - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } diff --git a/cmd/bucket-policy-handlers.go b/cmd/bucket-policy-handlers.go index 4a6c1af97..fbf453fc1 100644 --- a/cmd/bucket-policy-handlers.go +++ b/cmd/bucket-policy-handlers.go @@ -44,7 +44,7 @@ func (api objectAPIHandlers) PutBucketPolicyHandler(w http.ResponseWriter, r *ht objAPI := api.ObjectAPI() if objAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } @@ -52,43 +52,43 @@ func (api objectAPIHandlers) PutBucketPolicyHandler(w http.ResponseWriter, r *ht bucket := vars["bucket"] if s3Error := checkRequestAuthType(ctx, r, policy.PutBucketPolicyAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Check if bucket exists. if _, err := objAPI.GetBucketInfo(ctx, bucket); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } // Error out if Content-Length is missing. // PutBucketPolicy always needs Content-Length. if r.ContentLength <= 0 { - writeErrorResponse(w, ErrMissingContentLength, r.URL) + writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) return } // Error out if Content-Length is beyond allowed size. if r.ContentLength > maxBucketPolicySize { - writeErrorResponse(w, ErrEntityTooLarge, r.URL) + writeErrorResponse(w, ErrEntityTooLarge, r.URL, guessIsBrowserReq(r)) return } bucketPolicy, err := policy.ParseConfig(io.LimitReader(r.Body, r.ContentLength), bucket) if err != nil { - writeErrorResponse(w, ErrMalformedPolicy, r.URL) + writeErrorResponse(w, ErrMalformedPolicy, r.URL, guessIsBrowserReq(r)) return } // Version in policy must not be empty if bucketPolicy.Version == "" { - writeErrorResponse(w, ErrMalformedPolicy, r.URL) + writeErrorResponse(w, ErrMalformedPolicy, r.URL, guessIsBrowserReq(r)) return } if err = objAPI.SetBucketPolicy(ctx, bucket, bucketPolicy); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -107,7 +107,7 @@ func (api objectAPIHandlers) DeleteBucketPolicyHandler(w http.ResponseWriter, r objAPI := api.ObjectAPI() if objAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } @@ -115,18 +115,18 @@ func (api objectAPIHandlers) DeleteBucketPolicyHandler(w http.ResponseWriter, r bucket := vars["bucket"] if s3Error := checkRequestAuthType(ctx, r, policy.DeleteBucketPolicyAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Check if bucket exists. if _, err := objAPI.GetBucketInfo(ctx, bucket); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } if err := objAPI.DeleteBucketPolicy(ctx, bucket); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -145,7 +145,7 @@ func (api objectAPIHandlers) GetBucketPolicyHandler(w http.ResponseWriter, r *ht objAPI := api.ObjectAPI() if objAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } @@ -153,26 +153,26 @@ func (api objectAPIHandlers) GetBucketPolicyHandler(w http.ResponseWriter, r *ht bucket := vars["bucket"] if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Check if bucket exists. if _, err := objAPI.GetBucketInfo(ctx, bucket); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } // Read bucket access policy. bucketPolicy, err := objAPI.GetBucketPolicy(ctx, bucket) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } policyData, err := json.Marshal(bucketPolicy) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } diff --git a/cmd/copy-part-range.go b/cmd/copy-part-range.go index a6f15d09b..2f2b319d2 100644 --- a/cmd/copy-part-range.go +++ b/cmd/copy-part-range.go @@ -22,16 +22,16 @@ import ( ) // Writes S3 compatible copy part range error. -func writeCopyPartErr(w http.ResponseWriter, err error, url *url.URL) { +func writeCopyPartErr(w http.ResponseWriter, err error, url *url.URL, browser bool) { switch err { case errInvalidRange: - writeErrorResponse(w, ErrInvalidCopyPartRange, url) + writeErrorResponse(w, ErrInvalidCopyPartRange, url, browser) return case errInvalidRangeSource: - writeErrorResponse(w, ErrInvalidCopyPartRangeSource, url) + writeErrorResponse(w, ErrInvalidCopyPartRangeSource, url, browser) return default: - writeErrorResponse(w, ErrInternalError, url) + writeErrorResponse(w, ErrInternalError, url, browser) return } } diff --git a/cmd/generic-handlers.go b/cmd/generic-handlers.go index 2a6b0789a..0032457c2 100644 --- a/cmd/generic-handlers.go +++ b/cmd/generic-handlers.go @@ -91,7 +91,7 @@ func setRequestHeaderSizeLimitHandler(h http.Handler) http.Handler { // of the user-defined metadata to 2 KB. func (h requestHeaderSizeLimitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if isHTTPHeaderSizeTooLarge(r.Header) { - writeErrorResponse(w, ErrMetadataTooLarge, r.URL) + writeErrorResponse(w, ErrMetadataTooLarge, r.URL, guessIsBrowserReq(r)) return } h.Handler.ServeHTTP(w, r) @@ -134,7 +134,7 @@ func filterReservedMetadata(h http.Handler) http.Handler { // would be treated as metadata. func (h reservedMetadataHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if containsReservedMetadata(r.Header) { - writeErrorResponse(w, ErrUnsupportedMetadata, r.URL) + writeErrorResponse(w, ErrUnsupportedMetadata, r.URL, guessIsBrowserReq(r)) return } h.Handler.ServeHTTP(w, r) @@ -300,7 +300,7 @@ func (h minioReservedBucketHandler) ServeHTTP(w http.ResponseWriter, r *http.Req // buckets bucketName, _ := urlPath2BucketObjectName(r.URL.Path) if isMinioReservedBucket(bucketName) || isMinioMetaBucket(bucketName) { - writeErrorResponse(w, ErrAllAccessDisabled, r.URL) + writeErrorResponse(w, ErrAllAccessDisabled, r.URL, guessIsBrowserReq(r)) return } } @@ -363,14 +363,14 @@ func (h timeValidityHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // All our internal APIs are sensitive towards Date // header, for all requests where Date header is not // present we will reject such clients. - writeErrorResponse(w, apiErr, r.URL) + writeErrorResponse(w, apiErr, r.URL, guessIsBrowserReq(r)) return } // Verify if the request date header is shifted by less than globalMaxSkewTime parameter in the past // or in the future, reject request otherwise. curTime := UTCNow() if curTime.Sub(amzDate) > globalMaxSkewTime || amzDate.Sub(curTime) > globalMaxSkewTime { - writeErrorResponse(w, ErrRequestTimeTooSkewed, r.URL) + writeErrorResponse(w, ErrRequestTimeTooSkewed, r.URL, guessIsBrowserReq(r)) return } } @@ -485,20 +485,20 @@ 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 != "" && objectName == "" { if ignoreNotImplementedBucketResources(r) { - writeErrorResponse(w, ErrNotImplemented, r.URL) + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) return } } // If bucketName and objectName are present check for its resource queries. if bucketName != "" && objectName != "" { if ignoreNotImplementedObjectResources(r) { - writeErrorResponse(w, ErrNotImplemented, r.URL) + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) return } } // A put method on path "/" doesn't make sense, ignore it. if r.Method == http.MethodPut && r.URL.Path == "/" { - writeErrorResponse(w, ErrNotImplemented, r.URL) + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) return } @@ -601,14 +601,14 @@ func hasBadPathComponent(path string) bool { func (h pathValidityHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Check for bad components in URL path. if hasBadPathComponent(r.URL.Path) { - writeErrorResponse(w, ErrInvalidResourceName, r.URL) + writeErrorResponse(w, ErrInvalidResourceName, r.URL, guessIsBrowserReq(r)) return } // Check for bad components in URL query values. for _, vv := range r.URL.Query() { for _, v := range vv { if hasBadPathComponent(v) { - writeErrorResponse(w, ErrInvalidResourceName, r.URL) + writeErrorResponse(w, ErrInvalidResourceName, r.URL, guessIsBrowserReq(r)) return } } @@ -653,9 +653,9 @@ func (f bucketForwardingHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques sr, err := globalDNSConfig.Get(bucket) if err != nil { if err == dns.ErrNoEntriesFound { - writeErrorResponse(w, ErrNoSuchBucket, r.URL) + writeErrorResponse(w, ErrNoSuchBucket, r.URL, guessIsBrowserReq(r)) } else { - writeErrorResponse(w, toAPIErrorCode(context.Background(), err), r.URL) + writeErrorResponse(w, toAPIErrorCode(context.Background(), err), r.URL, guessIsBrowserReq(r)) } return } @@ -716,7 +716,7 @@ func (l rateLimit) ServeHTTP(w http.ResponseWriter, r *http.Request) { // potential pileup on the server. if err := l.Wait(ctx); err != nil { // Send an S3 compatible error, SlowDown. - writeErrorResponse(w, ErrSlowDown, r.URL) + writeErrorResponse(w, ErrSlowDown, r.URL, guessIsBrowserReq(r)) return } @@ -768,7 +768,7 @@ type criticalErrorHandler struct{ handler http.Handler } func (h criticalErrorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer func() { if err := recover(); err == logger.ErrCritical { // handle - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) } else if err != nil { panic(err) // forward other panic calls } @@ -787,7 +787,7 @@ func (h sseTLSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodHead { writeErrorResponseHeadersOnly(w, ErrInsecureSSECustomerRequest) } else { - writeErrorResponse(w, ErrInsecureSSECustomerRequest, r.URL) + writeErrorResponse(w, ErrInsecureSSECustomerRequest, r.URL, guessIsBrowserReq(r)) } return } diff --git a/cmd/handler-utils.go b/cmd/handler-utils.go index 955035d71..3fb915015 100644 --- a/cmd/handler-utils.go +++ b/cmd/handler-utils.go @@ -351,6 +351,6 @@ func getResource(path string, host string, domain string) (string, error) { // If none of the http routes match respond with MethodNotAllowed func notFoundHandler(w http.ResponseWriter, r *http.Request) { - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } diff --git a/cmd/object-handlers-common.go b/cmd/object-handlers-common.go index 722b5dba8..d0a6a32aa 100644 --- a/cmd/object-handlers-common.go +++ b/cmd/object-handlers-common.go @@ -75,7 +75,7 @@ func checkCopyObjectPreconditions(w http.ResponseWriter, r *http.Request, objInf if !ifModifiedSince(objInfo.ModTime, givenTime) { // If the object is not modified since the specified time. writeHeaders() - writeErrorResponse(w, ErrPreconditionFailed, r.URL) + writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) return true } } @@ -89,7 +89,7 @@ func checkCopyObjectPreconditions(w http.ResponseWriter, r *http.Request, objInf if ifModifiedSince(objInfo.ModTime, givenTime) { // If the object is modified since the specified time. writeHeaders() - writeErrorResponse(w, ErrPreconditionFailed, r.URL) + writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) return true } } @@ -102,7 +102,7 @@ func checkCopyObjectPreconditions(w http.ResponseWriter, r *http.Request, objInf if objInfo.ETag != "" && !isETagEqual(objInfo.ETag, ifMatchETagHeader) { // If the object ETag does not match with the specified ETag. writeHeaders() - writeErrorResponse(w, ErrPreconditionFailed, r.URL) + writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) return true } } @@ -114,7 +114,7 @@ func checkCopyObjectPreconditions(w http.ResponseWriter, r *http.Request, objInf if objInfo.ETag != "" && isETagEqual(objInfo.ETag, ifNoneMatchETagHeader) { // If the object ETag matches with the specified ETag. writeHeaders() - writeErrorResponse(w, ErrPreconditionFailed, r.URL) + writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) return true } } @@ -174,7 +174,7 @@ func checkPreconditions(w http.ResponseWriter, r *http.Request, objInfo ObjectIn if ifModifiedSince(objInfo.ModTime, givenTime) { // If the object is modified since the specified time. writeHeaders() - writeErrorResponse(w, ErrPreconditionFailed, r.URL) + writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) return true } } @@ -187,7 +187,7 @@ func checkPreconditions(w http.ResponseWriter, r *http.Request, objInfo ObjectIn if !isETagEqual(objInfo.ETag, ifMatchETagHeader) { // If the object ETag does not match with the specified ETag. writeHeaders() - writeErrorResponse(w, ErrPreconditionFailed, r.URL) + writeErrorResponse(w, ErrPreconditionFailed, r.URL, guessIsBrowserReq(r)) return true } } diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 54b7eb9c8..b88e6694b 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -84,11 +84,11 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r // Fetch object stat info. objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if crypto.S3KMS.IsRequested(r.Header) { // SSE-KMS is not supported - writeErrorResponse(w, ErrNotImplemented, r.URL) + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) return } vars := mux.Vars(r) @@ -129,33 +129,33 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r } } } - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Get request range. rangeHeader := r.Header.Get("Range") if rangeHeader != "" { - writeErrorResponse(w, ErrUnsupportedRangeHeader, r.URL) + writeErrorResponse(w, ErrUnsupportedRangeHeader, r.URL, guessIsBrowserReq(r)) return } if r.ContentLength <= 0 { - writeErrorResponse(w, ErrEmptyRequestBody, r.URL) + writeErrorResponse(w, ErrEmptyRequestBody, r.URL, guessIsBrowserReq(r)) return } var selectReq s3select.ObjectSelectRequest if err := xmlDecoder(r.Body, &selectReq, r.ContentLength); err != nil { - writeErrorResponse(w, ErrMalformedXML, r.URL) + writeErrorResponse(w, ErrMalformedXML, r.URL, guessIsBrowserReq(r)) return } if !strings.EqualFold(string(selectReq.ExpressionType), "SQL") { - writeErrorResponse(w, ErrInvalidExpressionType, r.URL) + writeErrorResponse(w, ErrInvalidExpressionType, r.URL, guessIsBrowserReq(r)) return } if len(selectReq.Expression) >= s3select.MaxExpressionLength { - writeErrorResponse(w, ErrExpressionTooLong, r.URL) + writeErrorResponse(w, ErrExpressionTooLong, r.URL, guessIsBrowserReq(r)) return } @@ -167,7 +167,7 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r var opts ObjectOptions gr, err := getObjectNInfo(ctx, bucket, object, nil, r.Header, readLock, opts) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } defer gr.Close() @@ -176,37 +176,37 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r if selectReq.InputSerialization.CompressionType == s3select.SelectCompressionGZIP { if !strings.Contains(objInfo.ContentType, "gzip") { - writeErrorResponse(w, ErrInvalidDataSource, r.URL) + writeErrorResponse(w, ErrInvalidDataSource, r.URL, guessIsBrowserReq(r)) return } } if selectReq.InputSerialization.CompressionType == s3select.SelectCompressionBZIP { if !strings.Contains(objInfo.ContentType, "bzip") { - writeErrorResponse(w, ErrInvalidDataSource, r.URL) + writeErrorResponse(w, ErrInvalidDataSource, r.URL, guessIsBrowserReq(r)) return } } if selectReq.InputSerialization.CompressionType == "" { selectReq.InputSerialization.CompressionType = s3select.SelectCompressionNONE if !strings.Contains(objInfo.ContentType, "text/csv") && !strings.Contains(objInfo.ContentType, "application/json") { - writeErrorResponse(w, ErrInvalidDataSource, r.URL) + writeErrorResponse(w, ErrInvalidDataSource, r.URL, guessIsBrowserReq(r)) return } } if !strings.EqualFold(string(selectReq.ExpressionType), "SQL") { - writeErrorResponse(w, ErrInvalidExpressionType, r.URL) + writeErrorResponse(w, ErrInvalidExpressionType, r.URL, guessIsBrowserReq(r)) return } if len(selectReq.Expression) >= s3select.MaxExpressionLength { - writeErrorResponse(w, ErrExpressionTooLong, r.URL) + writeErrorResponse(w, ErrExpressionTooLong, r.URL, guessIsBrowserReq(r)) return } if selectReq.InputSerialization.CSV == nil && selectReq.InputSerialization.JSON == nil { - writeErrorResponse(w, ErrInvalidRequestParameter, r.URL) + writeErrorResponse(w, ErrInvalidRequestParameter, r.URL, guessIsBrowserReq(r)) return } if selectReq.OutputSerialization.CSV == nil && selectReq.OutputSerialization.JSON == nil { - writeErrorResponse(w, ErrInvalidRequestParameter, r.URL) + writeErrorResponse(w, ErrInvalidRequestParameter, r.URL, guessIsBrowserReq(r)) return } @@ -215,24 +215,24 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r selectReq.InputSerialization.CSV.FileHeaderInfo != s3select.CSVFileHeaderInfoNone && selectReq.InputSerialization.CSV.FileHeaderInfo != s3select.CSVFileHeaderInfoIgnore && selectReq.InputSerialization.CSV.FileHeaderInfo != "" { - writeErrorResponse(w, ErrInvalidFileHeaderInfo, r.URL) + writeErrorResponse(w, ErrInvalidFileHeaderInfo, r.URL, guessIsBrowserReq(r)) return } if selectReq.OutputSerialization.CSV.QuoteFields != s3select.CSVQuoteFieldsAlways && selectReq.OutputSerialization.CSV.QuoteFields != s3select.CSVQuoteFieldsAsNeeded && selectReq.OutputSerialization.CSV.QuoteFields != "" { - writeErrorResponse(w, ErrInvalidQuoteFields, r.URL) + writeErrorResponse(w, ErrInvalidQuoteFields, r.URL, guessIsBrowserReq(r)) return } if len(selectReq.InputSerialization.CSV.RecordDelimiter) > 2 { - writeErrorResponse(w, ErrInvalidRequestParameter, r.URL) + writeErrorResponse(w, ErrInvalidRequestParameter, r.URL, guessIsBrowserReq(r)) return } } if selectReq.InputSerialization.JSON != nil { if selectReq.InputSerialization.JSON.Type != s3select.JSONLinesType { - writeErrorResponse(w, ErrInvalidJSONType, r.URL) + writeErrorResponse(w, ErrInvalidJSONType, r.URL, guessIsBrowserReq(r)) return } @@ -258,21 +258,21 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r if objInfo.IsCompressed() { size = objInfo.GetActualSize() if size < 0 { - writeErrorResponse(w, toAPIErrorCode(ctx, errInvalidDecompressedSize), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, errInvalidDecompressedSize), r.URL, guessIsBrowserReq(r)) return } } s3s, err := s3select.New(reader, size, selectReq) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } // Parses the select query and checks for an error _, _, _, _, _, _, err = s3select.ParseSelect(s3s) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -309,11 +309,11 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if crypto.S3.IsRequested(r.Header) || crypto.S3KMS.IsRequested(r.Header) { // If SSE-S3 or SSE-KMS present -> AWS fails with undefined error - writeErrorResponse(w, ErrBadRequest, r.URL) + writeErrorResponse(w, ErrBadRequest, r.URL, guessIsBrowserReq(r)) return } @@ -359,7 +359,7 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req } } } - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -377,7 +377,7 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req // parse error and treat it as regular Get // request like Amazon S3. if err == errInvalidRange { - writeErrorResponse(w, ErrInvalidRange, r.URL) + writeErrorResponse(w, ErrInvalidRange, r.URL, guessIsBrowserReq(r)) return } @@ -387,7 +387,7 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req gr, err := getObjectNInfo(ctx, bucket, object, rs, r.Header, readLock, opts) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } defer gr.Close() @@ -396,7 +396,7 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req if objectAPI.IsEncryptionSupported() { if _, err = DecryptObjectInfo(&objInfo, r.Header); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -420,7 +420,7 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req } if err = setObjectHeaders(w, objInfo, rs); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -436,14 +436,14 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req // Write object content to response body if _, err = io.Copy(httpWriter, gr); err != nil { if !httpWriter.HasWritten() && !statusCodeWritten { // write error response only if no data or headers has been written to client yet - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) } return } if err = httpWriter.Close(); err != nil { if !httpWriter.HasWritten() && !statusCodeWritten { // write error response only if no data or headers has been written to client yet - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -481,7 +481,7 @@ func (api objectAPIHandlers) HeadObjectHandler(w http.ResponseWriter, r *http.Re return } if crypto.S3.IsRequested(r.Header) || crypto.S3KMS.IsRequested(r.Header) { // If SSE-S3 or SSE-KMS present -> AWS fails with undefined error - writeErrorResponse(w, ErrBadRequest, r.URL) + writeErrorResponse(w, ErrBadRequest, r.URL, guessIsBrowserReq(r)) return } @@ -660,11 +660,11 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if crypto.S3KMS.IsRequested(r.Header) { - writeErrorResponse(w, ErrNotImplemented, r.URL) // SSE-KMS is not supported + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) // SSE-KMS is not supported return } @@ -673,7 +673,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re dstObject := vars["object"] if s3Error := checkRequestAuthType(ctx, r, policy.PutObjectAction, dstBucket, dstObject); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -689,18 +689,18 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re srcBucket, srcObject := path2BucketAndObject(cpSrcPath) // If source object is empty or bucket is empty, reply back invalid copy source. if srcObject == "" || srcBucket == "" { - writeErrorResponse(w, ErrInvalidCopySource, r.URL) + writeErrorResponse(w, ErrInvalidCopySource, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.GetObjectAction, srcBucket, srcObject); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Check if metadata directive is valid. if !isMetadataDirectiveValid(r.Header) { - writeErrorResponse(w, ErrInvalidMetadataDirective, r.URL) + writeErrorResponse(w, ErrInvalidMetadataDirective, r.URL, guessIsBrowserReq(r)) return } @@ -709,7 +709,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re // Deny if WORM is enabled if globalWORMEnabled { if _, err = objectAPI.GetObjectInfo(ctx, dstBucket, dstObject, dstOpts); err == nil { - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } } @@ -729,7 +729,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re var rs *HTTPRangeSpec gr, err := getObjectNInfo(ctx, srcBucket, srcObject, rs, r.Header, lock, srcOpts) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } defer gr.Close() @@ -742,7 +742,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re /// maximum Upload size for object in a single CopyObject operation. if isMaxObjectSize(srcInfo.Size) { - writeErrorResponse(w, ErrEntityTooLarge, r.URL) + writeErrorResponse(w, ErrEntityTooLarge, r.URL, guessIsBrowserReq(r)) return } @@ -771,7 +771,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re if crypto.IsEncrypted(srcInfo.UserDefined) { actualSize, err = srcInfo.DecryptedSize() if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -810,7 +810,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re srcInfo.Reader, err = hash.NewReader(reader, length, "", "", actualSize) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } rawReader := srcInfo.Reader @@ -819,12 +819,12 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re if objectAPI.IsEncryptionSupported() && !isCompressed { // Encryption parameters not applicable for this object. if !crypto.IsEncrypted(srcInfo.UserDefined) && crypto.SSECopy.IsRequested(r.Header) { - writeErrorResponse(w, toAPIErrorCode(ctx, errInvalidEncryptionParameters), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, errInvalidEncryptionParameters), r.URL, guessIsBrowserReq(r)) return } // Encryption parameters not present for this object. if crypto.SSEC.IsEncrypted(srcInfo.UserDefined) && !crypto.SSECopy.IsRequested(r.Header) { - writeErrorResponse(w, ErrInvalidSSECustomerAlgorithm, r.URL) + writeErrorResponse(w, ErrInvalidSSECustomerAlgorithm, r.URL, guessIsBrowserReq(r)) return } @@ -840,7 +840,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re if sseC { newKey, err = ParseSSECustomerRequest(r) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -853,7 +853,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re if sseCopyC && sseC { oldKey, err = ParseSSECopyCustomerRequest(r.Header, srcInfo.UserDefined) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -863,7 +863,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re // In case of SSE-S3 oldKey and newKey aren't used - the KMS manages the keys. if err = rotateKey(oldKey, newKey, srcBucket, srcObject, encMetadata); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -894,7 +894,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re if isTargetEncrypted { reader, objEncKey, err = newEncryptReader(srcInfo.Reader, newKey, dstBucket, dstObject, encMetadata, sseS3) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -907,7 +907,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re srcInfo.Reader, err = hash.NewReader(reader, targetSize, "", "", targetSize) // do not try to verify encrypted content if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } pReader = NewPutObjReader(rawReader, srcInfo.Reader, objEncKey) @@ -918,7 +918,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re srcInfo.UserDefined, err = getCpObjMetadataFromHeader(ctx, r, srcInfo.UserDefined) if err != nil { - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) return } @@ -939,7 +939,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re if !isMetadataReplace(r.Header) && srcInfo.metadataOnly && !crypto.IsEncrypted(srcInfo.UserDefined) { // If x-amz-metadata-directive is not set to REPLACE then we need // to error out if source and destination are same. - writeErrorResponse(w, ErrInvalidCopyDest, r.URL) + writeErrorResponse(w, ErrInvalidCopyDest, r.URL, guessIsBrowserReq(r)) return } @@ -958,7 +958,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re if isRemoteCallRequired(ctx, srcBucket, dstBucket, objectAPI) { if globalDNSConfig == nil { - writeErrorResponse(w, ErrNoSuchBucket, r.URL) + writeErrorResponse(w, ErrNoSuchBucket, r.URL, guessIsBrowserReq(r)) return } var dstRecords []dns.SrvRecord @@ -967,12 +967,12 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re host, port := getRandomHostPort(dstRecords) client, rerr := getRemoteInstanceClient(host, port) if rerr != nil { - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) return } remoteObjInfo, rerr := client.PutObject(dstBucket, dstObject, srcInfo.Reader, srcInfo.Size, "", "", srcInfo.UserDefined, dstOpts.ServerSideEncryption) if rerr != nil { - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) return } objInfo.ETag = remoteObjInfo.ETag @@ -983,7 +983,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re // object is same then only metadata is updated. objInfo, err = objectAPI.CopyObject(ctx, srcBucket, srcObject, dstBucket, dstObject, srcInfo, srcOpts, dstOpts) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -1032,11 +1032,11 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if crypto.S3KMS.IsRequested(r.Header) { - writeErrorResponse(w, ErrNotImplemented, r.URL) // SSE-KMS is not supported + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) // SSE-KMS is not supported return } @@ -1046,14 +1046,14 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req // X-Amz-Copy-Source shouldn't be set for this call. if _, ok := r.Header["X-Amz-Copy-Source"]; ok { - writeErrorResponse(w, ErrInvalidCopySource, r.URL) + writeErrorResponse(w, ErrInvalidCopySource, r.URL, guessIsBrowserReq(r)) return } // Validate storage class metadata if present if _, ok := r.Header[amzStorageClassCanonical]; ok { if !isValidStorageClassMeta(r.Header.Get(amzStorageClassCanonical)) { - writeErrorResponse(w, ErrInvalidStorageClass, r.URL) + writeErrorResponse(w, ErrInvalidStorageClass, r.URL, guessIsBrowserReq(r)) return } } @@ -1061,7 +1061,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req // Get Content-Md5 sent by client and verify if valid md5Bytes, err := checkValidMD5(r.Header) if err != nil { - writeErrorResponse(w, ErrInvalidDigest, r.URL) + writeErrorResponse(w, ErrInvalidDigest, r.URL, guessIsBrowserReq(r)) return } /// if Content-Length is unknown/missing, deny the request @@ -1070,30 +1070,30 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req if rAuthType == authTypeStreamingSigned { if sizeStr, ok := r.Header["X-Amz-Decoded-Content-Length"]; ok { if sizeStr[0] == "" { - writeErrorResponse(w, ErrMissingContentLength, r.URL) + writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) return } size, err = strconv.ParseInt(sizeStr[0], 10, 64) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } } if size == -1 { - writeErrorResponse(w, ErrMissingContentLength, r.URL) + writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) return } /// maximum Upload size for objects in a single operation if isMaxObjectSize(size) { - writeErrorResponse(w, ErrEntityTooLarge, r.URL) + writeErrorResponse(w, ErrEntityTooLarge, r.URL, guessIsBrowserReq(r)) return } metadata, err := extractMetadata(ctx, r) if err != nil { - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) return } @@ -1128,7 +1128,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req // Check if put is allowed if s3Err = isPutAllowed(rAuthType, bucket, object, r); s3Err != ErrNone { - writeErrorResponse(w, s3Err, r.URL) + writeErrorResponse(w, s3Err, r.URL, guessIsBrowserReq(r)) return } @@ -1137,19 +1137,19 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req // Initialize stream signature verifier. reader, s3Err = newSignV4ChunkedReader(r) if s3Err != ErrNone { - writeErrorResponse(w, s3Err, r.URL) + writeErrorResponse(w, s3Err, r.URL, guessIsBrowserReq(r)) return } case authTypeSignedV2, authTypePresignedV2: s3Err = isReqAuthenticatedV2(r) if s3Err != ErrNone { - writeErrorResponse(w, s3Err, r.URL) + writeErrorResponse(w, s3Err, r.URL, guessIsBrowserReq(r)) return } case authTypePresigned, authTypeSigned: if s3Err = reqSignatureV4Verify(r, globalServerConfig.GetRegion()); s3Err != ErrNone { - writeErrorResponse(w, s3Err, r.URL) + writeErrorResponse(w, s3Err, r.URL, guessIsBrowserReq(r)) return } if !skipContentSha256Cksum(r) { @@ -1170,7 +1170,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req var actualReader *hash.Reader actualReader, err = hash.NewReader(reader, size, md5hex, sha256hex, actualSize) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1190,7 +1190,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req hashReader, err := hash.NewReader(reader, size, md5hex, sha256hex, actualSize) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1202,7 +1202,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req // Deny if WORM is enabled if globalWORMEnabled { if _, err = objectAPI.GetObjectInfo(ctx, bucket, object, opts); err == nil { - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } } @@ -1211,13 +1211,13 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req if hasServerSideEncryptionHeader(r.Header) && !hasSuffix(object, slashSeparator) { // handle SSE requests reader, objectEncryptionKey, err = EncryptRequest(hashReader, r, bucket, object, metadata) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } info := ObjectInfo{Size: size} hashReader, err = hash.NewReader(reader, info.EncryptedSize(), "", "", size) // do not try to verify encrypted content if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } pReader = NewPutObjReader(rawReader, hashReader, objectEncryptionKey) @@ -1234,7 +1234,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req // Create the object.. objInfo, err := putObject(ctx, bucket, object, pReader, metadata, opts) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1295,11 +1295,11 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if crypto.S3KMS.IsRequested(r.Header) { - writeErrorResponse(w, ErrNotImplemented, r.URL) // SSE-KMS is not supported + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) // SSE-KMS is not supported return } @@ -1312,14 +1312,14 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r err error ) if s3Error := checkRequestAuthType(ctx, r, policy.PutObjectAction, bucket, object); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Deny if WORM is enabled if globalWORMEnabled { if _, err = objectAPI.GetObjectInfo(ctx, bucket, object, opts); err == nil { - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } } @@ -1327,7 +1327,7 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r // Validate storage class metadata if present if _, ok := r.Header[amzStorageClassCanonical]; ok { if !isValidStorageClassMeta(r.Header.Get(amzStorageClassCanonical)) { - writeErrorResponse(w, ErrInvalidStorageClass, r.URL) + writeErrorResponse(w, ErrInvalidStorageClass, r.URL, guessIsBrowserReq(r)) return } } @@ -1337,7 +1337,7 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r if objectAPI.IsEncryptionSupported() { if hasServerSideEncryptionHeader(r.Header) { if err = setEncryptionMetadata(r, bucket, object, encMetadata); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } // Set this for multipart only operations, we need to differentiate during @@ -1349,7 +1349,7 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r // Extract metadata that needs to be saved. metadata, err := extractMetadata(ctx, r) if err != nil { - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) return } @@ -1373,7 +1373,7 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r } uploadID, err := newMultipartUpload(ctx, bucket, object, metadata, opts) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1392,11 +1392,11 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if crypto.S3KMS.IsRequested(r.Header) { - writeErrorResponse(w, ErrNotImplemented, r.URL) // SSE-KMS is not supported + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) // SSE-KMS is not supported return } @@ -1405,7 +1405,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt dstObject := vars["object"] if s3Error := checkRequestAuthType(ctx, r, policy.PutObjectAction, dstBucket, dstObject); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -1419,12 +1419,12 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt srcBucket, srcObject := path2BucketAndObject(cpSrcPath) // If source object is empty or bucket is empty, reply back invalid copy source. if srcObject == "" || srcBucket == "" { - writeErrorResponse(w, ErrInvalidCopySource, r.URL) + writeErrorResponse(w, ErrInvalidCopySource, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.GetObjectAction, srcBucket, srcObject); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -1433,13 +1433,13 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt partID, err := strconv.Atoi(partIDString) if err != nil { - writeErrorResponse(w, ErrInvalidPart, r.URL) + writeErrorResponse(w, ErrInvalidPart, r.URL, guessIsBrowserReq(r)) return } // check partID with maximum part ID for multipart objects if isMaxPartID(partID) { - writeErrorResponse(w, ErrInvalidMaxParts, r.URL) + writeErrorResponse(w, ErrInvalidMaxParts, r.URL, guessIsBrowserReq(r)) return } @@ -1448,7 +1448,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt // Deny if WORM is enabled if globalWORMEnabled { if _, err = objectAPI.GetObjectInfo(ctx, dstBucket, dstObject, dstOpts); err == nil { - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } } @@ -1468,7 +1468,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt // Ignore other parse error and treat it as regular Get request like Amazon S3. logger.GetReqInfo(ctx).AppendTags("rangeHeader", rangeHeader) logger.LogIf(ctx, parseRangeErr) - writeCopyPartErr(w, parseRangeErr, r.URL) + writeCopyPartErr(w, parseRangeErr, r.URL, guessIsBrowserReq(r)) return } @@ -1476,7 +1476,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt gr, err := getObjectNInfo(ctx, srcBucket, srcObject, rs, r.Header, readLock, srcOpts) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } defer gr.Close() @@ -1486,14 +1486,14 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt if crypto.IsEncrypted(srcInfo.UserDefined) { actualPartSize, err = srcInfo.DecryptedSize() if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } // Special care for CopyObjectPart if partRangeErr := checkCopyPartRangeWithSize(rs, actualPartSize); partRangeErr != nil { - writeCopyPartErr(w, partRangeErr, r.URL) + writeCopyPartErr(w, partRangeErr, r.URL, guessIsBrowserReq(r)) return } @@ -1505,13 +1505,13 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt // Get the object offset & length startOffset, length, err := rs.GetOffsetLength(actualPartSize) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } /// maximum copy size for multipart objects in a single operation if isMaxAllowedPartSize(length) { - writeErrorResponse(w, ErrEntityTooLarge, r.URL) + writeErrorResponse(w, ErrEntityTooLarge, r.URL, guessIsBrowserReq(r)) return } @@ -1521,7 +1521,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt var li ListPartsInfo li, err = objectAPI.ListObjectParts(ctx, dstBucket, dstObject, uploadID, 0, 1) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1551,7 +1551,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt srcInfo.Reader, err = hash.NewReader(reader, length, "", "", actualPartSize) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1563,11 +1563,11 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt if objectAPI.IsEncryptionSupported() && !isCompressed { if crypto.IsEncrypted(li.UserDefined) { if !crypto.SSEC.IsRequested(r.Header) && crypto.SSEC.IsEncrypted(li.UserDefined) { - writeErrorResponse(w, ErrSSEMultipartEncrypted, r.URL) + writeErrorResponse(w, ErrSSEMultipartEncrypted, r.URL, guessIsBrowserReq(r)) return } if crypto.S3.IsEncrypted(li.UserDefined) && crypto.SSEC.IsRequested(r.Header) { - writeErrorResponse(w, ErrSSEMultipartEncrypted, r.URL) + writeErrorResponse(w, ErrSSEMultipartEncrypted, r.URL, guessIsBrowserReq(r)) return } isEncrypted = true // to detect SSE-S3 encryption @@ -1575,13 +1575,13 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt if crypto.SSEC.IsRequested(r.Header) { key, err = ParseSSECustomerRequest(r) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } objectEncryptionKey, err = decryptObjectInfo(key, dstBucket, dstObject, li.UserDefined) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1593,14 +1593,14 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt partEncryptionKey := mac.Sum(nil) reader, err = sio.EncryptReader(reader, sio.Config{Key: partEncryptionKey}) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } info := ObjectInfo{Size: length} srcInfo.Reader, err = hash.NewReader(reader, info.EncryptedSize(), "", "", length) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } pReader = NewPutObjReader(rawReader, srcInfo.Reader, objectEncryptionKey) @@ -1613,7 +1613,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt partInfo, err := objectAPI.CopyObjectPart(ctx, srcBucket, srcObject, dstBucket, dstObject, uploadID, partID, startOffset, length, srcInfo, srcOpts, dstOpts) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1636,11 +1636,11 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if crypto.S3KMS.IsRequested(r.Header) { - writeErrorResponse(w, ErrNotImplemented, r.URL) // SSE-KMS is not supported + writeErrorResponse(w, ErrNotImplemented, r.URL, guessIsBrowserReq(r)) // SSE-KMS is not supported return } @@ -1650,14 +1650,14 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http // X-Amz-Copy-Source shouldn't be set for this call. if _, ok := r.Header["X-Amz-Copy-Source"]; ok { - writeErrorResponse(w, ErrInvalidCopySource, r.URL) + writeErrorResponse(w, ErrInvalidCopySource, r.URL, guessIsBrowserReq(r)) return } // get Content-Md5 sent by client and verify if valid md5Bytes, err := checkValidMD5(r.Header) if err != nil { - writeErrorResponse(w, ErrInvalidDigest, r.URL) + writeErrorResponse(w, ErrInvalidDigest, r.URL, guessIsBrowserReq(r)) return } @@ -1669,24 +1669,24 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http if rAuthType == authTypeStreamingSigned { if sizeStr, ok := r.Header["X-Amz-Decoded-Content-Length"]; ok { if sizeStr[0] == "" { - writeErrorResponse(w, ErrMissingContentLength, r.URL) + writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) return } size, err = strconv.ParseInt(sizeStr[0], 10, 64) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } } if size == -1 { - writeErrorResponse(w, ErrMissingContentLength, r.URL) + writeErrorResponse(w, ErrMissingContentLength, r.URL, guessIsBrowserReq(r)) return } /// maximum Upload size for multipart objects in a single operation if isMaxAllowedPartSize(size) { - writeErrorResponse(w, ErrEntityTooLarge, r.URL) + writeErrorResponse(w, ErrEntityTooLarge, r.URL, guessIsBrowserReq(r)) return } @@ -1695,13 +1695,13 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http partID, err := strconv.Atoi(partIDString) if err != nil { - writeErrorResponse(w, ErrInvalidPart, r.URL) + writeErrorResponse(w, ErrInvalidPart, r.URL, guessIsBrowserReq(r)) return } // check partID with maximum part ID for multipart objects if isMaxPartID(partID) { - writeErrorResponse(w, ErrInvalidMaxParts, r.URL) + writeErrorResponse(w, ErrInvalidMaxParts, r.URL, guessIsBrowserReq(r)) return } @@ -1713,7 +1713,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http ) reader = r.Body if s3Error = isPutAllowed(rAuthType, bucket, object, r); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -1722,17 +1722,17 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http // Initialize stream signature verifier. reader, s3Error = newSignV4ChunkedReader(r) if s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } case authTypeSignedV2, authTypePresignedV2: if s3Error = isReqAuthenticatedV2(r); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } case authTypePresigned, authTypeSigned: if s3Error = reqSignatureV4Verify(r, globalServerConfig.GetRegion()); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -1748,7 +1748,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http var li ListPartsInfo li, err = objectAPI.ListObjectParts(ctx, bucket, object, uploadID, 0, 1) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } // Read compression metadata preserved in the init multipart for the decision. @@ -1762,7 +1762,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http var actualReader *hash.Reader actualReader, err = hash.NewReader(reader, size, md5hex, sha256hex, actualSize) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1783,7 +1783,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http hashReader, err := hash.NewReader(reader, size, md5hex, sha256hex, actualSize) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1794,7 +1794,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http // Deny if WORM is enabled if globalWORMEnabled { if _, err = objectAPI.GetObjectInfo(ctx, bucket, object, opts); err == nil { - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } } @@ -1805,12 +1805,12 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http var li ListPartsInfo li, err = objectAPI.ListObjectParts(ctx, bucket, object, uploadID, 0, 1) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } if crypto.IsEncrypted(li.UserDefined) { if !crypto.SSEC.IsRequested(r.Header) && crypto.SSEC.IsEncrypted(li.UserDefined) { - writeErrorResponse(w, ErrSSEMultipartEncrypted, r.URL) + writeErrorResponse(w, ErrSSEMultipartEncrypted, r.URL, guessIsBrowserReq(r)) return } isEncrypted = true // to detect SSE-S3 encryption @@ -1818,7 +1818,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http if crypto.SSEC.IsRequested(r.Header) { key, err = ParseSSECustomerRequest(r) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -1826,7 +1826,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http // Calculating object encryption key objectEncryptionKey, err = decryptObjectInfo(key, bucket, object, li.UserDefined) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1839,13 +1839,13 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http reader, err = sio.EncryptReader(hashReader, sio.Config{Key: partEncryptionKey}) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } info := ObjectInfo{Size: size} hashReader, err = hash.NewReader(reader, info.EncryptedSize(), "", "", size) // do not try to verify encrypted content if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } pReader = NewPutObjReader(rawReader, hashReader, objectEncryptionKey) @@ -1859,7 +1859,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http partInfo, err := putObjectPart(ctx, bucket, object, uploadID, partID, pReader, opts) if err != nil { // Verify if the underlying error is signature mismatch. - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } if isCompressed { @@ -1891,7 +1891,7 @@ func (api objectAPIHandlers) AbortMultipartUploadHandler(w http.ResponseWriter, objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } abortMultipartUpload := objectAPI.AbortMultipartUpload @@ -1900,25 +1900,25 @@ func (api objectAPIHandlers) AbortMultipartUploadHandler(w http.ResponseWriter, } if s3Error := checkRequestAuthType(ctx, r, policy.AbortMultipartUploadAction, bucket, object); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Deny if WORM is enabled if globalWORMEnabled { if _, err := objectAPI.GetObjectInfo(ctx, bucket, object, ObjectOptions{}); err == nil { - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } } uploadID, _, _, _, s3Error := getObjectResources(r.URL.Query()) if s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } if err := abortMultipartUpload(ctx, bucket, object, uploadID); err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1937,31 +1937,31 @@ func (api objectAPIHandlers) ListObjectPartsHandler(w http.ResponseWriter, r *ht objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.ListMultipartUploadPartsAction, bucket, object); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } uploadID, partNumberMarker, maxParts, _, s3Error := getObjectResources(r.URL.Query()) if s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } if partNumberMarker < 0 { - writeErrorResponse(w, ErrInvalidPartNumberMarker, r.URL) + writeErrorResponse(w, ErrInvalidPartNumberMarker, r.URL, guessIsBrowserReq(r)) return } if maxParts < 0 { - writeErrorResponse(w, ErrInvalidMaxParts, r.URL) + writeErrorResponse(w, ErrInvalidMaxParts, r.URL, guessIsBrowserReq(r)) return } listPartsInfo, err := objectAPI.ListObjectParts(ctx, bucket, object, uploadID, partNumberMarker, maxParts) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } @@ -1970,7 +1970,7 @@ func (api objectAPIHandlers) ListObjectPartsHandler(w http.ResponseWriter, r *ht var li ListPartsInfo li, err = objectAPI.ListObjectParts(ctx, bucket, object, uploadID, 0, 1) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } if crypto.IsEncrypted(li.UserDefined) { @@ -1983,7 +1983,7 @@ func (api objectAPIHandlers) ListObjectPartsHandler(w http.ResponseWriter, r *ht // Calculating object encryption key objectEncryptionKey, err = decryptObjectInfo(key, bucket, object, li.UserDefined) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -2016,19 +2016,19 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.PutObjectAction, bucket, object); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } // Deny if WORM is enabled if globalWORMEnabled { if _, err := objectAPI.GetObjectInfo(ctx, bucket, object, ObjectOptions{}); err == nil { - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } } @@ -2036,26 +2036,26 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite // Get upload id. uploadID, _, _, _, s3Error := getObjectResources(r.URL.Query()) if s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } completeMultipartBytes, err := goioutil.ReadAll(r.Body) if err != nil { - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) return } complMultipartUpload := &CompleteMultipartUpload{} if err = xml.Unmarshal(completeMultipartBytes, complMultipartUpload); err != nil { - writeErrorResponse(w, ErrMalformedXML, r.URL) + writeErrorResponse(w, ErrMalformedXML, r.URL, guessIsBrowserReq(r)) return } if len(complMultipartUpload.Parts) == 0 { - writeErrorResponse(w, ErrMalformedXML, r.URL) + writeErrorResponse(w, ErrMalformedXML, r.URL, guessIsBrowserReq(r)) return } if !sort.IsSorted(CompletedParts(complMultipartUpload.Parts)) { - writeErrorResponse(w, ErrInvalidPartOrder, r.URL) + writeErrorResponse(w, ErrInvalidPartOrder, r.URL, guessIsBrowserReq(r)) return } var objectEncryptionKey []byte @@ -2066,7 +2066,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite var li ListPartsInfo li, err = objectAPI.ListObjectParts(ctx, bucket, object, uploadID, 0, 1) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } if crypto.IsEncrypted(li.UserDefined) { @@ -2077,7 +2077,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite // Calculating object encryption key objectEncryptionKey, err = decryptObjectInfo(key, bucket, object, li.UserDefined) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } } @@ -2093,7 +2093,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite for { listPartsInfo, err = objectAPI.ListObjectParts(ctx, bucket, object, uploadID, partNumberMarker, maxParts) if err != nil { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) return } for _, part := range listPartsInfo.Parts { @@ -2120,7 +2120,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite if bkPartInfo, ok := partsMap[strconv.Itoa(part.PartNumber)]; ok { bkETag := tryDecryptETag(objectEncryptionKey, bkPartInfo.ETag, ssec) if bkETag != part.ETag { - writeErrorResponse(w, ErrInvalidPart, r.URL) + writeErrorResponse(w, ErrInvalidPart, r.URL, guessIsBrowserReq(r)) return } part.ETag = bkPartInfo.ETag @@ -2141,7 +2141,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite writePartSmallErrorResponse(w, r, oErr) default: // Handle all other generic issues. - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) } return } @@ -2152,7 +2152,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite response := generateCompleteMultpartUploadResponse(bucket, object, location, objInfo.ETag) encodedSuccessResponse := encodeResponse(response) if err != nil { - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) return } @@ -2195,12 +2195,12 @@ func (api objectAPIHandlers) DeleteObjectHandler(w http.ResponseWriter, r *http. objectAPI := api.ObjectAPI() if objectAPI == nil { - writeErrorResponse(w, ErrServerNotInitialized, r.URL) + writeErrorResponse(w, ErrServerNotInitialized, r.URL, guessIsBrowserReq(r)) return } if s3Error := checkRequestAuthType(ctx, r, policy.DeleteObjectAction, bucket, object); s3Error != ErrNone { - writeErrorResponse(w, s3Error, r.URL) + writeErrorResponse(w, s3Error, r.URL, guessIsBrowserReq(r)) return } @@ -2208,7 +2208,7 @@ func (api objectAPIHandlers) DeleteObjectHandler(w http.ResponseWriter, r *http. if globalWORMEnabled { // Not required to check whether given object exists or not, because // DeleteObject is always successful irrespective of object existence. - writeErrorResponse(w, ErrMethodNotAllowed, r.URL) + writeErrorResponse(w, ErrMethodNotAllowed, r.URL, guessIsBrowserReq(r)) return } @@ -2216,9 +2216,9 @@ func (api objectAPIHandlers) DeleteObjectHandler(w http.ResponseWriter, r *http. _, err := globalDNSConfig.Get(bucket) if err != nil { if err == dns.ErrNoEntriesFound { - writeErrorResponse(w, ErrNoSuchBucket, r.URL) + writeErrorResponse(w, ErrNoSuchBucket, r.URL, guessIsBrowserReq(r)) } else { - writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL) + writeErrorResponse(w, toAPIErrorCode(ctx, err), r.URL, guessIsBrowserReq(r)) } return } @@ -2229,7 +2229,7 @@ func (api objectAPIHandlers) DeleteObjectHandler(w http.ResponseWriter, r *http. switch toAPIErrorCode(ctx, err) { case ErrNoSuchBucket: // When bucket doesn't exist specially handle it. - writeErrorResponse(w, ErrNoSuchBucket, r.URL) + writeErrorResponse(w, ErrNoSuchBucket, r.URL, guessIsBrowserReq(r)) return } // Ignore delete object errors while replying to client, since we are suppposed to reply only 204. diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index 0aec44ef2..077d7dbd1 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -768,7 +768,7 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) { // Extract incoming metadata if any. metadata, err := extractMetadata(context.Background(), r) if err != nil { - writeErrorResponse(w, ErrInternalError, r.URL) + writeErrorResponse(w, ErrInternalError, r.URL, guessIsBrowserReq(r)) return }