diff --git a/internal/services/storage_backend_s3.go b/internal/services/storage_backend_s3.go index 264a3bc..4e77b71 100644 --- a/internal/services/storage_backend_s3.go +++ b/internal/services/storage_backend_s3.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net/url" + "strings" "time" "github.com/minio/minio-go/v7" @@ -25,11 +26,22 @@ func NewS3Backend(endpoint, keyID, appKey, bucket string, useSSL bool, region st region = "us-east-1" } - client, err := minio.New(endpoint, &minio.Options{ + opts := &minio.Options{ Creds: credentials.NewStaticV4(keyID, appKey, ""), Secure: useSSL, Region: region, - }) + } + // B2's S3-compatible endpoint only implements POST Object on + // virtual-hosted-style URLs (https://.s3..backblazeb2.com/). + // Path-style POST returns HTTP 501. minio-go's auto-detection falls back + // to path-style for non-AWS endpoints, which breaks PresignedPostPolicy + // against B2. Force DNS lookup for B2 only — leave MinIO dev (no DNS for + // arbitrary buckets at minio:9000) on the path-style default. + if strings.Contains(endpoint, "backblazeb2.com") { + opts.BucketLookup = minio.BucketLookupDNS + } + + client, err := minio.New(endpoint, opts) if err != nil { return nil, fmt.Errorf("failed to create S3 client: %w", err) }