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

Update presign post URL resolution to use the exact result from EndpointResolverV2 #2842

Merged
merged 4 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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/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,43 @@
/*
* 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 = $internalContext:L.$setFunc:L(ctx, endpt.URI.String())
""",
Map.of(
"internalContext", AwsGoDependency.INTERNAL_CONTEXT.getAlias(),
"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
12 changes: 12 additions & 0 deletions internal/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
type s3BackendKey struct{}
type checksumInputAlgorithmKey struct{}
type clockSkew struct{}
type s3resolvedURI struct{}

const (
// S3BackendS3Express identifies the S3Express backend
Expand Down Expand Up @@ -50,3 +51,14 @@ func GetAttemptSkewContext(ctx context.Context) time.Duration {
x, _ := middleware.GetStackValue(ctx, clockSkew{}).(time.Duration)
return x
}

// SetS3ResolvedURI sets the URI as resolved by the EndpointResolverV2
func SetS3ResolvedURI(ctx context.Context, value string) context.Context {
Madrigal marked this conversation as resolved.
Show resolved Hide resolved
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
}
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 := internalcontext.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
37 changes: 30 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,23 @@ func TestPresignPutObject(t *testing.T) {
},
expectedURL: "https://mfzwi23gnjvgw.mrap.accesspoint.s3-global.amazonaws.com",
},
"use path style bucket hosting pattern": {
Madrigal marked this conversation as resolved.
Show resolved Hide resolved
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",
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
Expand All @@ -81,8 +100,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