Skip to content

Commit

Permalink
Update presign post URL resolution to use the exact result from Endpo…
Browse files Browse the repository at this point in the history
…intResolverV2 (#2842)

* Update presign post URL resolution to use the exact result from EndpointResolverV2
  • Loading branch information
Madrigal authored Oct 25, 2024
1 parent 866d441 commit 63c2a37
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 23 deletions.
8 changes: 8 additions & 0 deletions .changelog/5702f383099a47a5860f5ab25cda67a1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"id": "5702f383-099a-47a5-860f-5ab25cda67a1",
"type": "bugfix",
"description": "Update presign post URL resolution to use the exact result from EndpointResolverV2",
"modules": [
"service/s3"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package software.amazon.smithy.aws.go.codegen.customization.s3;

import software.amazon.smithy.aws.go.codegen.AwsGoDependency;
import software.amazon.smithy.aws.go.codegen.customization.S3ModelUtils;
import software.amazon.smithy.go.codegen.GoSettings;
import software.amazon.smithy.go.codegen.GoWriter;
import software.amazon.smithy.go.codegen.integration.GoIntegration;
import software.amazon.smithy.model.Model;

import java.util.Map;

/**
* Stores the endpoint resolved by EndpointResolverV2
*/
public class StoreResolvedUri implements GoIntegration {
@Override
public void renderPostEndpointResolutionHook(GoSettings settings, GoWriter writer, Model model) {
if (!S3ModelUtils.isServiceS3(model, settings.getService(model))) return;
writer.writeGoTemplate(
"""
ctx = $setFunc:L(ctx, endpt.URI.String())
""",
Map.of(
"setFunc", "setS3ResolvedURI")
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ software.amazon.smithy.aws.go.codegen.customization.RemoveDefaults
software.amazon.smithy.aws.go.codegen.customization.auth.S3ExpressAuthScheme
software.amazon.smithy.aws.go.codegen.customization.S3BucketContext
software.amazon.smithy.aws.go.codegen.customization.s3.ExpressDefaultChecksum
software.amazon.smithy.aws.go.codegen.customization.s3.StoreResolvedUri
software.amazon.smithy.aws.go.codegen.customization.auth.GlobalAnonymousOption
software.amazon.smithy.aws.go.codegen.customization.CloudFrontKVSSigV4a
software.amazon.smithy.aws.go.codegen.customization.BackfillProtocolTestServiceTrait
Expand Down
2 changes: 2 additions & 0 deletions service/s3/endpoints.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 2 additions & 16 deletions service/s3/presign_post.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"net/url"
"strings"
"time"

Expand Down Expand Up @@ -211,10 +210,6 @@ func (s *presignPostRequestMiddleware) HandleFinalize(
) (
out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
) {
req, ok := in.Request.(*smithyhttp.Request)
if !ok {
return out, metadata, fmt.Errorf("unexpected request middleware type %T", in.Request)
}

input := getOperationInput(ctx)
asS3Put, ok := input.(*PutObjectInput)
Expand All @@ -230,8 +225,7 @@ func (s *presignPostRequestMiddleware) HandleFinalize(
return out, metadata, fmt.Errorf("PutObject input does not have a key input")
}

httpReq := req.Build(ctx)
u := httpReq.URL.String()
uri := getS3ResolvedURI(ctx)

signingName := awsmiddleware.GetSigningName(ctx)
signingRegion := awsmiddleware.GetSigningRegion(ctx)
Expand Down Expand Up @@ -265,22 +259,14 @@ 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)

out.Result = &PresignedPostRequest{
URL: baseURL,
URL: uri,
Values: fields,
}

return out, metadata, nil
}

func toBaseURL(fullURL string) string {
a, _ := url.Parse(fullURL)
return a.Scheme + "://" + a.Host
}

// Adapted from existing PresignConverter middleware
func (c presignPostConverter) ConvertToPresignMiddleware(stack *middleware.Stack, options Options) (err error) {
stack.Build.Remove("UserAgent")
Expand Down
60 changes: 53 additions & 7 deletions service/s3/presign_post_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,26 @@ 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{
Bucket: aws.String("bucket"),
Key: aws.String("key"),
},
},
"bucket and key have the same value": {
input: PutObjectInput{
Bucket: aws.String("bucket"),
Key: aws.String("bucket"),
},
},
"expires override": {
input: PutObjectInput{
Bucket: aws.String("bucket"),
Expand Down Expand Up @@ -66,6 +74,40 @@ func TestPresignPutObject(t *testing.T) {
},
expectedURL: "https://mfzwi23gnjvgw.mrap.accesspoint.s3-global.amazonaws.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 and key have the same value ": {
input: PutObjectInput{
Bucket: aws.String("value"),
Key: aws.String("value"),
},
expectedURL: "https://s3.us-west-2.amazonaws.com/value",
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",
},
"use path style bucket with custom baseEndpoint with path": {
input: PutObjectInput{
Bucket: aws.String("bucket"),
Key: aws.String("key"),
},
BaseEndpoint: "https://my-custom-domain.com/path_my_path",
pathStyleEnabled: true,
expectedURL: "https://my-custom-domain.com/path_my_path/bucket",
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
Expand All @@ -81,8 +123,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
23 changes: 23 additions & 0 deletions service/s3/uri_context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package s3

// This contains helper methods to set resolver URI into the context object. If they are ever used for
// something other than S3, they should be moved to internal/context/context.go

import (
"context"

"github.com/aws/smithy-go/middleware"
)

type s3resolvedURI struct{}

// setS3ResolvedURI sets the URI as resolved by the EndpointResolverV2
func setS3ResolvedURI(ctx context.Context, value string) context.Context {
return middleware.WithStackValue(ctx, s3resolvedURI{}, value)
}

// getS3ResolvedURI gets the URI as resolved by EndpointResolverV2
func getS3ResolvedURI(ctx context.Context) string {
v, _ := middleware.GetStackValue(ctx, s3resolvedURI{}).(string)
return v
}

0 comments on commit 63c2a37

Please sign in to comment.