Skip to content

Commit 7e320c6

Browse files
author
You
committed
fix(storage): preserve custom host in S3 presigned URLs
1 parent 6baafdb commit 7e320c6

3 files changed

Lines changed: 90 additions & 2 deletions

File tree

drivers/s3/util.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
awsconfig "github.com/aws/aws-sdk-go-v2/config"
1515
"github.com/aws/aws-sdk-go-v2/credentials"
1616
awss3 "github.com/aws/aws-sdk-go-v2/service/s3"
17+
smithyendpoints "github.com/aws/smithy-go/endpoints"
1718
log "github.com/sirupsen/logrus"
1819
)
1920

@@ -43,7 +44,10 @@ func (d *S3) initSession(ctx context.Context) error {
4344
d.client = d.newClient(d.Endpoint)
4445
d.linkClient = d.client
4546
if d.CustomHost != "" && d.EnableCustomHostPresign {
46-
d.linkClient = d.newClient(normalizeEndpoint(d.CustomHost))
47+
d.linkClient, err = d.newCustomHostClient()
48+
if err != nil {
49+
return err
50+
}
4751
}
4852
return nil
4953
}
@@ -57,6 +61,33 @@ func (d *S3) newClient(endpoint string) *awss3.Client {
5761
})
5862
}
5963

64+
type customHostEndpointResolver struct {
65+
endpoint url.URL
66+
}
67+
68+
func (r customHostEndpointResolver) ResolveEndpoint(
69+
_ context.Context,
70+
params awss3.EndpointParameters,
71+
) (smithyendpoints.Endpoint, error) {
72+
endpoint := r.endpoint
73+
if aws.ToBool(params.ForcePathStyle) && params.Bucket != nil {
74+
endpoint = *endpoint.JoinPath(*params.Bucket)
75+
}
76+
return smithyendpoints.Endpoint{URI: endpoint}, nil
77+
}
78+
79+
func (d *S3) newCustomHostClient() (*awss3.Client, error) {
80+
endpoint, err := url.Parse(normalizeEndpoint(d.CustomHost))
81+
if err != nil {
82+
return nil, err
83+
}
84+
client := awss3.NewFromConfig(d.awsConfig, func(options *awss3.Options) {
85+
options.EndpointResolverV2 = customHostEndpointResolver{endpoint: *endpoint}
86+
options.UsePathStyle = d.ForcePathStyle
87+
})
88+
return client, nil
89+
}
90+
6091
func normalizeEndpoint(endpoint string) string {
6192
if strings.Contains(endpoint, "://") {
6293
return endpoint

drivers/s3/util_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package s3
22

33
import (
4+
"context"
5+
"net/url"
46
"testing"
57

8+
"github.com/AlliotTech/openalist/internal/model"
69
"github.com/stretchr/testify/assert"
710
"github.com/stretchr/testify/require"
811
)
@@ -51,3 +54,57 @@ func TestCustomObjectURL(t *testing.T) {
5154
})
5255
}
5356
}
57+
58+
func TestCustomHostPresign(t *testing.T) {
59+
tests := []struct {
60+
name string
61+
forcePathStyle bool
62+
removeBucket bool
63+
wantHost string
64+
wantPath string
65+
}{
66+
{
67+
name: "virtual host style keeps custom host",
68+
wantHost: "cdn.example.com",
69+
wantPath: "/base/dir/file.txt",
70+
},
71+
{
72+
name: "path style keeps bucket in path",
73+
forcePathStyle: true,
74+
wantHost: "cdn.example.com",
75+
wantPath: "/base/bucket/dir/file.txt",
76+
},
77+
{
78+
name: "remove bucket keeps custom host",
79+
forcePathStyle: true,
80+
removeBucket: true,
81+
wantHost: "cdn.example.com",
82+
wantPath: "/base/dir/file.txt",
83+
},
84+
}
85+
86+
for _, tt := range tests {
87+
t.Run(tt.name, func(t *testing.T) {
88+
d := S3{Addition: Addition{
89+
AccessKeyID: "access-key",
90+
SecretAccessKey: "secret-key",
91+
Region: "us-east-1",
92+
Bucket: "bucket",
93+
CustomHost: "https://cdn.example.com/base",
94+
EnableCustomHostPresign: true,
95+
ForcePathStyle: tt.forcePathStyle,
96+
RemoveBucket: tt.removeBucket,
97+
SignURLExpire: 1,
98+
}}
99+
require.NoError(t, d.Init(context.Background()))
100+
101+
link, err := d.Link(context.Background(), &model.Object{Path: "/dir/file.txt"}, model.LinkArgs{})
102+
require.NoError(t, err)
103+
parsed, err := url.Parse(link.URL)
104+
require.NoError(t, err)
105+
assert.Equal(t, tt.wantHost, parsed.Host)
106+
assert.Equal(t, tt.wantPath, parsed.Path)
107+
assert.NotEmpty(t, parsed.Query().Get("X-Amz-Signature"))
108+
})
109+
}
110+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ require (
2020
github.com/aws/aws-sdk-go-v2/credentials v1.19.14
2121
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.13
2222
github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0
23+
github.com/aws/smithy-go v1.24.3
2324
github.com/blevesearch/bleve/v2 v2.6.0
2425
github.com/caarlos0/env/v9 v9.0.0
2526
github.com/charmbracelet/bubbles v1.0.0
@@ -105,7 +106,6 @@ require (
105106
github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 // indirect
106107
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 // indirect
107108
github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect
108-
github.com/aws/smithy-go v1.24.3 // indirect
109109
github.com/blevesearch/zapx/v17 v17.1.2 // indirect
110110
github.com/bytedance/gopkg v0.1.3 // indirect
111111
github.com/charmbracelet/colorprofile v0.4.1 // indirect

0 commit comments

Comments
 (0)