package storage import ( "context" "errors" "time" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" ) type S3Config struct { Endpoint string Region string Bucket string AccessKey string SecretKey string UseTLS bool PathStyle bool } type S3Signer struct { client *minio.Client bucket string } func NewS3Signer(cfg S3Config) (*S3Signer, error) { if cfg.Endpoint == "" || cfg.Bucket == "" { return nil, errors.New("s3 endpoint and bucket are required") } client, err := minio.New(cfg.Endpoint, &minio.Options{ Creds: credentials.NewStaticV4(cfg.AccessKey, cfg.SecretKey, ""), Secure: cfg.UseTLS, Region: cfg.Region, BucketLookup: bucketLookup(cfg.PathStyle), }) if err != nil { return nil, err } return &S3Signer{client: client, bucket: cfg.Bucket}, nil } func bucketLookup(pathStyle bool) minio.BucketLookupType { if pathStyle { return minio.BucketLookupPath } return minio.BucketLookupAuto } func (s *S3Signer) SignedPutObjectURL(ctx context.Context, objectKey string, expiry time.Duration, _ string) (string, error) { u, err := s.client.PresignedPutObject(ctx, s.bucket, objectKey, expiry) if err != nil { return "", err } return u.String(), nil } func (s *S3Signer) SignedGetObjectURL(ctx context.Context, objectKey string, expiry time.Duration) (string, error) { u, err := s.client.PresignedGetObject(ctx, s.bucket, objectKey, expiry, nil) if err != nil { return "", err } return u.String(), nil }