1/* 2 * MinIO Go Library for Amazon S3 Compatible Cloud Storage 3 * Copyright 2015-2020 MinIO, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package minio 19 20import ( 21 "context" 22 "net/http" 23 "net/url" 24 25 "github.com/minio/minio-go/v7/pkg/s3utils" 26) 27 28// BucketExists verifies if bucket exists and you have permission to access it. Allows for a Context to 29// control cancellations and timeouts. 30func (c Client) BucketExists(ctx context.Context, bucketName string) (bool, error) { 31 // Input validation. 32 if err := s3utils.CheckValidBucketName(bucketName); err != nil { 33 return false, err 34 } 35 36 // Execute HEAD on bucketName. 37 resp, err := c.executeMethod(ctx, http.MethodHead, requestMetadata{ 38 bucketName: bucketName, 39 contentSHA256Hex: emptySHA256Hex, 40 }) 41 defer closeResponse(resp) 42 if err != nil { 43 if ToErrorResponse(err).Code == "NoSuchBucket" { 44 return false, nil 45 } 46 return false, err 47 } 48 if resp != nil { 49 resperr := httpRespToErrorResponse(resp, bucketName, "") 50 if ToErrorResponse(resperr).Code == "NoSuchBucket" { 51 return false, nil 52 } 53 if resp.StatusCode != http.StatusOK { 54 return false, httpRespToErrorResponse(resp, bucketName, "") 55 } 56 } 57 return true, nil 58} 59 60// StatObject verifies if object exists and you have permission to access. 61func (c Client) StatObject(ctx context.Context, bucketName, objectName string, opts StatObjectOptions) (ObjectInfo, error) { 62 // Input validation. 63 if err := s3utils.CheckValidBucketName(bucketName); err != nil { 64 return ObjectInfo{}, err 65 } 66 if err := s3utils.CheckValidObjectName(objectName); err != nil { 67 return ObjectInfo{}, err 68 } 69 return c.statObject(ctx, bucketName, objectName, opts) 70} 71 72// Lower level API for statObject supporting pre-conditions and range headers. 73func (c Client) statObject(ctx context.Context, bucketName, objectName string, opts StatObjectOptions) (ObjectInfo, error) { 74 // Input validation. 75 if err := s3utils.CheckValidBucketName(bucketName); err != nil { 76 return ObjectInfo{}, err 77 } 78 if err := s3utils.CheckValidObjectName(objectName); err != nil { 79 return ObjectInfo{}, err 80 } 81 headers := opts.Header() 82 if opts.Internal.ReplicationDeleteMarker { 83 headers.Set(minIOBucketReplicationDeleteMarker, "true") 84 } 85 86 urlValues := make(url.Values) 87 if opts.VersionID != "" { 88 urlValues.Set("versionId", opts.VersionID) 89 } 90 // Execute HEAD on objectName. 91 resp, err := c.executeMethod(ctx, http.MethodHead, requestMetadata{ 92 bucketName: bucketName, 93 objectName: objectName, 94 queryValues: urlValues, 95 contentSHA256Hex: emptySHA256Hex, 96 customHeader: headers, 97 }) 98 defer closeResponse(resp) 99 if err != nil { 100 return ObjectInfo{}, err 101 } 102 deleteMarker := resp.Header.Get(amzDeleteMarker) == "true" 103 104 if resp != nil { 105 if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusPartialContent { 106 if resp.StatusCode == http.StatusBadRequest && opts.VersionID != "" && deleteMarker { 107 errResp := ErrorResponse{ 108 StatusCode: resp.StatusCode, 109 Code: "MethodNotAllowed", 110 Message: "The specified method is not allowed against this resource.", 111 BucketName: bucketName, 112 Key: objectName, 113 } 114 return ObjectInfo{ 115 VersionID: resp.Header.Get(amzVersionID), 116 IsDeleteMarker: deleteMarker, 117 }, errResp 118 } 119 return ObjectInfo{ 120 VersionID: resp.Header.Get(amzVersionID), 121 IsDeleteMarker: deleteMarker, 122 }, httpRespToErrorResponse(resp, bucketName, objectName) 123 } 124 } 125 126 return ToObjectInfo(bucketName, objectName, resp.Header) 127} 128