fix(worker): use EndpointResolverV2 for ARMOR B2 uploads

The BaseEndpoint approach with older aws-sdk-go-v2 causes
"Invalid region: region was not a valid DNS name" errors when
uploading to ARMOR's S3-compatible endpoint.

Switching to EndpointResolverV2 bypasses the SDK's endpoint
rule validation entirely, resolving the issue.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-04-28 23:33:56 -04:00
parent c9cdafe9ca
commit ee8c7c37b2

View file

@ -5,11 +5,13 @@ import (
"bytes"
"context"
"fmt"
"net/url"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
smithyendpoints "github.com/aws/smithy-go/endpoints"
)
// B2Client handles B2 bucket operations (S3-compatible).
@ -21,6 +23,12 @@ type B2Client struct {
// NewB2Client creates a new B2 client.
func NewB2Client(cfg *Config) *B2Client {
// Parse and validate the custom endpoint
endpointURL, err := url.Parse(cfg.B2Endpoint)
if err != nil {
panic(fmt.Sprintf("failed to parse B2 endpoint: %v", err))
}
// Load AWS config with B2 credentials
// For S3-compatible endpoints (ARMOR/B2), the region is not used
// but must be set to a valid value for the SDK
@ -37,9 +45,11 @@ func NewB2Client(cfg *Config) *B2Client {
}
// Create S3 client with custom endpoint (ARMOR proxy wrapping B2)
// Use custom EndpointResolverV2 to bypass endpoint rules entirely
client := s3.NewFromConfig(awsCfg, func(o *s3.Options) {
o.BaseEndpoint = aws.String(cfg.B2Endpoint)
o.UsePathStyle = true // Required for ARMOR/B2 S3-compatible API
o.EndpointResolverV2 = &customEndpointResolver{
endpointURL: *endpointURL,
}
})
return &B2Client{
@ -122,3 +132,14 @@ func (c *B2Client) List(ctx context.Context, prefix string) ([]string, error) {
func (c *B2Client) Endpoint() string {
return c.endpoint
}
// customEndpointResolver implements s3.EndpointResolverV2 for custom S3-compatible endpoints.
type customEndpointResolver struct {
endpointURL url.URL
}
func (r *customEndpointResolver) ResolveEndpoint(ctx context.Context, params s3.EndpointParameters) (smithyendpoints.Endpoint, error) {
return smithyendpoints.Endpoint{
URI: r.endpointURL,
}, nil
}