package s3 import ( "errors" "net/http" "regexp" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" ) // Open creates a store using an injected credential provider and transport. // The application owns transport shutdown; no global HTTP defaults are changed. type Config struct { Endpoint string `json:"endpoint"` // Host[:port], without scheme or path. Region string `json:"region"` Bucket string `json:"bucket"` Secure bool `json:"secure"` MaxBytes int64 `json:"maxBytes"` Credentials *credentials.Credentials `json:"-"` Transport http.RoundTripper `json:"-"` } func Open(cfg Config) (*Store, error) { if cfg.Credentials == nil { return nil, errors.New("storage/s3: credentials provider required") } client, err := minio.New(cfg.Endpoint, &minio.Options{Creds: cfg.Credentials, Secure: cfg.Secure, Region: cfg.Region, Transport: cfg.Transport, BucketLookup: minio.BucketLookupPath}) if err != nil { return nil, err } return New(client, cfg.Bucket, cfg.MaxBytes) } // R2Config selects Cloudflare's standard S3 API endpoint. Jurisdiction-specific // endpoints can be set explicitly with Config. R2 implements an S3 subset. func R2Config(accountID, bucket string, creds *credentials.Credentials) (Config, error) { if !regexp.MustCompile(`^[a-fA-F0-9]{32}$`).MatchString(accountID) { return Config{}, errors.New("storage/s3: invalid R2 account ID") } return Config{Endpoint: accountID + ".r2.cloudflarestorage.com", Region: "auto", Bucket: bucket, Secure: true, Credentials: creds}, nil }