Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for path style in presigned Post #2835

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changelog/7762e0d93d3e4d549a85c7174feaff94.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"id": "7762e0d9-3d3e-4d54-9a85-c7174feaff94",
"type": "bugfix",
"description": "Added support for path style urls and overrides in presigned post",
"modules": [
"service/s3"
]
}
28 changes: 26 additions & 2 deletions service/s3/presign_post.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"log"
"net/url"
"strings"
"time"
Expand Down Expand Up @@ -166,6 +167,9 @@ type PresignPostOptions struct {
//
// [here]https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html#sigv4-PolicyConditions
Conditions []interface{}

// BaseURLOverride provides an override for the presigner
BaseURLOverride *string
}

type presignPostConverter PresignPostOptions
Expand All @@ -177,6 +181,7 @@ type presignPostRequestMiddlewareOptions struct {
LogSigning bool
ExpiresIn time.Duration
Conditions []interface{}
BaseURLOverride *string
}

type presignPostRequestMiddleware struct {
Expand All @@ -185,6 +190,7 @@ type presignPostRequestMiddleware struct {
logSigning bool
expiresIn time.Duration
conditions []interface{}
BaseURLOverride *string
}

// newPresignPostRequestMiddleware returns a new presignPostRequestMiddleware
Expand All @@ -196,6 +202,7 @@ func newPresignPostRequestMiddleware(options presignPostRequestMiddlewareOptions
logSigning: options.LogSigning,
expiresIn: options.ExpiresIn,
conditions: options.Conditions,
BaseURLOverride: options.BaseURLOverride,
}
}

Expand Down Expand Up @@ -267,6 +274,9 @@ func (s *presignPostRequestMiddleware) HandleFinalize(

// Other middlewares may set default values on the URL on the path or as query params. Remove them
baseURL := toBaseURL(u)
if s.BaseURLOverride != nil {
baseURL = *s.BaseURLOverride
}

out.Result = &PresignedPostRequest{
URL: baseURL,
Expand All @@ -277,8 +287,21 @@ func (s *presignPostRequestMiddleware) HandleFinalize(
}

func toBaseURL(fullURL string) string {
a, _ := url.Parse(fullURL)
return a.Scheme + "://" + a.Host
parsedURL, err := url.Parse(fullURL)
if err != nil {
log.Printf("Invalid URL format: %v", err)
return ""
}
pathSegments := strings.Split(parsedURL.Path, "/")

if len(pathSegments) > 0 && pathSegments[0] == "" {
pathSegments = pathSegments[1:]
}

if len(pathSegments) > 1 {
return fmt.Sprintf("%s://%s/%s", parsedURL.Scheme, parsedURL.Host, pathSegments[0])
}
return fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host)
}

// Adapted from existing PresignConverter middleware
Expand All @@ -305,6 +328,7 @@ func (c presignPostConverter) ConvertToPresignMiddleware(stack *middleware.Stack
LogSigning: options.ClientLogMode.IsSigning(),
ExpiresIn: expiresIn,
Conditions: c.Conditions,
BaseURLOverride: c.BaseURLOverride,
})
if _, err := stack.Finalize.Swap("Signing", pmw); err != nil {
return err
Expand Down
63 changes: 56 additions & 7 deletions service/s3/presign_post_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ func TestPresignPutObject(t *testing.T) {
defer mockTime(fixedTime)()

cases := map[string]struct {
input PutObjectInput
options []func(*PresignPostOptions)
expectedExpires time.Time
expectedURL string
region string
input PutObjectInput
options []func(*PresignPostOptions)
expectedExpires time.Time
expectedURL string
region string
pathStyleEnabled bool
BaseEndpoint string
}{
"sample": {
input: PutObjectInput{
Expand Down Expand Up @@ -66,6 +68,49 @@ func TestPresignPutObject(t *testing.T) {
},
expectedURL: "https://mfzwi23gnjvgw.mrap.accesspoint.s3-global.amazonaws.com",
},
"override base url": {
input: PutObjectInput{
Bucket: aws.String("bucket"),
Key: aws.String("key"),
},
options: []func(o *PresignPostOptions){
func(o *PresignPostOptions) {
o.BaseURLOverride = aws.String("https://s3.custom-domain.com")
},
},
expectedURL: "https://s3.custom-domain.com",
},
"use path style bucket hosting pattern": {
input: PutObjectInput{
Bucket: aws.String("bucket"),
Key: aws.String("key"),
},
expectedURL: "https://s3.us-west-2.amazonaws.com/bucket",
pathStyleEnabled: true,
},
"use path style bucket with custom baseEndpoint": {
input: PutObjectInput{
Bucket: aws.String("bucket"),
Key: aws.String("key"),
},
expectedURL: "https://s3.custom-domain.com/bucket",
pathStyleEnabled: true,
BaseEndpoint: "https://s3.custom-domain.com",
},
"path style with baseEndpoint with url override option": {
input: PutObjectInput{
Bucket: aws.String("bucket"),
Key: aws.String("key"),
},
options: []func(o *PresignPostOptions){
func(o *PresignPostOptions) {
o.BaseURLOverride = aws.String("https://different-url.com")
},
},
expectedURL: "https://different-url.com",
pathStyleEnabled: true,
BaseEndpoint: "https://s3.custom-domain.com",
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
Expand All @@ -81,8 +126,12 @@ func TestPresignPutObject(t *testing.T) {
return aws.NopRetryer{}
},
}

presignClient := NewPresignClient(NewFromConfig(cfg))
presignClient := NewPresignClient(NewFromConfig(cfg, func(options *Options) {
options.UsePathStyle = tc.pathStyleEnabled
if tc.BaseEndpoint != "" {
options.BaseEndpoint = aws.String(tc.BaseEndpoint)
}
}))
postObject, err := presignClient.PresignPostObject(ctx, &tc.input, tc.options...)
if err != nil {
t.Error(err)
Expand Down
Loading