diff --git a/s3/s3.go b/s3/s3.go index e3000f03d81ba19c55df72851686649cbb96bd7f..bc550c35b8e8a66c19f47e5952869f37dcca5102 100644 --- a/s3/s3.go +++ b/s3/s3.go @@ -86,12 +86,15 @@ const ( var ( clients = map[string]*ClientWithHelpers{} + + ErrorS3ClientNotEstablished = errors.Error("could not establish an S3 client") ) type ClientWithHelpers struct { S3Client *s3.Client } +// GetClient gets an S3 client for the specified region. This function should never return a nil response. func GetClient(isDebug bool, region ...string) *ClientWithHelpers { s3Region := os.Getenv("AWS_REGION") @@ -101,7 +104,7 @@ func GetClient(isDebug bool, region ...string) *ClientWithHelpers { } // Check if client exists for region, if it does return it - if s3Client, ok := clients[s3Region]; ok { + if s3Client, ok := clients[s3Region]; ok && s3Client != nil { return s3Client } @@ -110,7 +113,7 @@ func GetClient(isDebug bool, region ...string) *ClientWithHelpers { config.WithCredentialsProvider(GetS3CredentialsProvider(isDebug)), ) if err != nil { - return nil + return &ClientWithHelpers{} } s3Client := NewClient(cfg) @@ -135,6 +138,10 @@ func NewClient(cfg aws.Config) *ClientWithHelpers { } func (s ClientWithHelpers) Upload(data []byte, bucket, fileName string, metadata *map[string]string) (*s3.PutObjectOutput, error) { + if s.S3Client == nil { + return nil, ErrorS3ClientNotEstablished + } + mimeType := getTypeForFilename(fileName) putInput := &s3.PutObjectInput{ Bucket: aws.String(bucket), @@ -156,6 +163,10 @@ func (s ClientWithHelpers) Upload(data []byte, bucket, fileName string, metadata } func (s ClientWithHelpers) UploadWithSettings(data []byte, bucket, fileName string, settings S3UploadSettings) (string, error) { + if s.S3Client == nil { + return "", ErrorS3ClientNotEstablished + } + if settings.MimeType == "" { settings.MimeType = getTypeForFilename(fileName) } @@ -200,6 +211,10 @@ func (s ClientWithHelpers) UploadWithSettings(data []byte, bucket, fileName stri // UploadWithSettingsRevised can be renamed to UploadWithSettings once original function has been deprecated. func (s ClientWithHelpers) UploadWithSettingsRevised(data []byte, bucket string, settings S3UploadSettings) (S3UploadResponse, error) { + if s.S3Client == nil { + return S3UploadResponse{}, ErrorS3ClientNotEstablished + } + var fullFileName, uploadUrl string uuidString := "" @@ -282,6 +297,10 @@ func (s ClientWithHelpers) UploadWithSettingsRevised(data []byte, bucket string, } func (s ClientWithHelpers) UploadWith1DayExpiry(data []byte, bucket, fileName string, mimeType MIMEType, shouldDownloadInsteadOfOpen bool) (string, error) { + if s.S3Client == nil { + return "", ErrorS3ClientNotEstablished + } + if mimeType == "" { mimeType = getTypeForFilename(fileName) } @@ -302,6 +321,10 @@ func (s ClientWithHelpers) UploadWith1DayExpiry(data []byte, bucket, fileName st // GetSignedDownloadURL gets a signed download URL for the duration. If scv is nil, a new session will be created. func (s ClientWithHelpers) GetSignedDownloadURL(bucket string, fileName string, duration time.Duration, headers ...map[string]string) (string, error) { + if s.S3Client == nil { + return "", ErrorS3ClientNotEstablished + } + fileExists, err := s.FileExists(bucket, fileName) if err != nil { return "", err @@ -335,6 +358,10 @@ func (s ClientWithHelpers) GetSignedDownloadURL(bucket string, fileName string, // GetSignedUploadURL gets a signed upload URL for the duration. If scv is nil, a new session will be created. func (s ClientWithHelpers) GetSignedUploadURL(bucket string, fileName string, duration time.Duration) (string, error) { + if s.S3Client == nil { + return "", ErrorS3ClientNotEstablished + } + putInput := &s3.PutObjectInput{ Bucket: aws.String(bucket), Key: aws.String(fileName), @@ -352,6 +379,10 @@ func (s ClientWithHelpers) GetSignedUploadURL(bucket string, fileName string, du } func (s ClientWithHelpers) FileExists(bucket string, fileName string) (bool, error) { + if s.S3Client == nil { + return false, ErrorS3ClientNotEstablished + } + _, err := s.S3Client.HeadObject(context.TODO(), &s3.HeadObjectInput{ Bucket: aws.String(bucket), Key: aws.String(fileName), @@ -368,6 +399,10 @@ func (s ClientWithHelpers) FileExists(bucket string, fileName string) (bool, err // UploadWithFileExtension will upload a file to S3 and return a standard S3UploadResponse. func (s ClientWithHelpers) UploadWithFileExtension(data []byte, bucket, filePrefix, fileExt string, mimeType MIMEType) (*S3UploadResponse, error) { + if s.S3Client == nil { + return nil, ErrorS3ClientNotEstablished + } + fileName := fmt.Sprintf("%s_%s.%s", filePrefix, uuid.New().String(), fileExt) duration := 24 * time.Hour @@ -410,6 +445,10 @@ func getTypeForFilename(f string) MIMEType { } func (s ClientWithHelpers) GetObject(bucket string, fileName string, isDebug bool) (*s3.GetObjectOutput, error) { + if s.S3Client == nil { + return nil, ErrorS3ClientNotEstablished + } + getInput := &s3.GetObjectInput{ Bucket: aws.String(bucket), Key: aws.String(fileName), @@ -422,6 +461,10 @@ func (s ClientWithHelpers) GetObject(bucket string, fileName string, isDebug boo } func (s ClientWithHelpers) GetObjectMetadata(bucket string, fileName string, isDebug bool) (map[string]string, error) { + if s.S3Client == nil { + return nil, ErrorS3ClientNotEstablished + } + headObjectInput := &s3.HeadObjectInput{ Bucket: aws.String(bucket), Key: aws.String(fileName), @@ -435,6 +478,9 @@ func (s ClientWithHelpers) GetObjectMetadata(bucket string, fileName string, isD // MoveObjectBucketToBucket - Move object from one S3 bucket to another func (s ClientWithHelpers) MoveObjectBucketToBucket(sourceBucket string, destinationBucket string, sourceFileName string, destinationFileName string, settings S3UploadSettings) error { + if s.S3Client == nil { + return ErrorS3ClientNotEstablished + } err := s.CopyObjectBucketToBucket(sourceBucket, destinationBucket, sourceFileName, destinationFileName, settings) if err != nil { @@ -451,6 +497,10 @@ func (s ClientWithHelpers) MoveObjectBucketToBucket(sourceBucket string, destina // CopyObjectBucketToBucket - Copy an object from one S3 bucket to another func (s ClientWithHelpers) CopyObjectBucketToBucket(sourceBucket string, destinationBucket string, sourceFileName string, destinationFilename string, settings S3UploadSettings) error { + if s.S3Client == nil { + return ErrorS3ClientNotEstablished + } + // copy the file copySource := url.QueryEscape(sourceBucket + "/" + sourceFileName) copyObjectInput := &s3.CopyObjectInput{ @@ -481,6 +531,10 @@ func (s ClientWithHelpers) CopyObjectBucketToBucket(sourceBucket string, destina // DeleteObjectFromBucket - Delete an object from an S3 bucket func (s ClientWithHelpers) DeleteObjectFromBucket(bucket string, fileName string) error { + if s.S3Client == nil { + return ErrorS3ClientNotEstablished + } + // delete the file deleteObjectInput := &s3.DeleteObjectInput{ Bucket: aws.String(bucket),