From c2c2f3848fa9a88d96952ff08f886483f8b9d1f7 Mon Sep 17 00:00:00 2001 From: bigbes Date: Sat, 18 Jul 2026 20:24:41 +0300 Subject: [PATCH] objects: force UnsignedPayload for S3 uploads (phoebe-lab patch) Carried production patch from the phoebe-lab SourceHut deployment (patches/core-go-checksum.patch). Fixes streaming PutObject to a non-AWS S3 backend (Garage) over plain HTTP, where the AWS SDK's dynamic payload middleware only uses UnsignedPayload over HTTPS and otherwise falls through to ComputePayloadSHA256, which seeks the non-seekable request body (pages Publish tarball, builds artifact stream) and fails. Force UnsignedPayload unconditionally and pin the sigv4 signing region so the endpoint resolver does not reset it. Not upstreamed. --- objects/middleware.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/objects/middleware.go b/objects/middleware.go index 98de38cadf44a66e410b12f504d0312c09d8157f..c4c6d95664e8adad61875dbee8431d8f673f7ae6 100644 --- a/objects/middleware.go +++ b/objects/middleware.go @@ -7,9 +7,11 @@ import ( "net/http" "github.com/aws/aws-sdk-go-v2/aws" + v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/smithy-go/endpoints" + smithymw "github.com/aws/smithy-go/middleware" "github.com/vaughan0/go-ini" "git.sr.ht/~sircmpwn/core-go/config" @@ -87,7 +89,19 @@ func NewClient(conf ini.File) (*s3.Client, error) { return s3.NewFromConfig(aws.Config{ Region: region, Credentials: creds, - }, func(opts *s3.Options) { + }, s3.WithSigV4SigningRegion(region), func(opts *s3.Options) { + // Patched (phoebe-lab): pages Publish + builds artifact upload pass + // non-seekable bodies (tar.Reader, io.LimitReader) to PutObject. The + // SDK's default dynamic-payload middleware only uses UnsignedPayload + // over HTTPS; over HTTP (s3-insecure=true to internal Garage) it + // falls through to ComputePayloadSHA256, which seeks the body and + // fails. Force UnsignedPayload unconditionally. The above + // WithSigV4SigningRegion pins the sigv4 region so the V1 endpoint + // resolver doesn't override it back to "default". + opts.APIOptions = append(opts.APIOptions, func(stack *smithymw.Stack) error { + _, err := stack.Finalize.Swap("ComputePayloadHash", &v4.UnsignedPayload{}) + return err + }) opts.BaseEndpoint = aws.String(scheme + upstream) opts.EndpointResolverV2 = &S3Resolver{ conf,