github.com/defang-io/defang/src@v0.0.0-20240505002154-bdf411911834/pkg/clouds/aws/ecs/upload.go (about)

     1  package ecs
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"regexp"
     7  
     8  	"github.com/aws/aws-sdk-go-v2/service/s3"
     9  	"github.com/aws/smithy-go/ptr"
    10  	"github.com/google/uuid"
    11  )
    12  
    13  // From https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html
    14  var s3InvalidCharsRegexp = regexp.MustCompile(`[^a-zA-Z0-9!_.*'()-]`)
    15  
    16  const prefix = "uploads/"
    17  
    18  func (a *AwsEcs) CreateUploadURL(ctx context.Context, name string) (string, error) {
    19  	cfg, err := a.LoadConfig(ctx)
    20  	if err != nil {
    21  		return "", err
    22  	}
    23  
    24  	if name == "" {
    25  		name = uuid.NewString()
    26  	} else {
    27  		if len(name) > 64 {
    28  			return "", errors.New("name must be less than 64 characters")
    29  		}
    30  		// Sanitize the digest so it's safe to use as a file name
    31  		name = s3InvalidCharsRegexp.ReplaceAllString(name, "_")
    32  		// name = path.Join(buildsPath, tenantId.String(), digest); TODO: avoid collisions between tenants
    33  	}
    34  
    35  	s3Client := s3.NewFromConfig(cfg)
    36  	// Use S3 SDK to create a presigned URL for uploading a file.
    37  	req, err := s3.NewPresignClient(s3Client).PresignPutObject(ctx, &s3.PutObjectInput{
    38  		Bucket: &a.BucketName,
    39  		Key:    ptr.String(prefix + name),
    40  	})
    41  	if err != nil {
    42  		return "", err
    43  	}
    44  	return req.URL, nil
    45  }