[#7153] eagerly escape the S3 path in accordance with the S3 UriEncode signing rules

This commit is contained in:
Gani Georgiev
2025-09-06 11:59:32 +03:00
parent 28de01a188
commit 1359a6f8fd
3 changed files with 40 additions and 10 deletions

View File

@@ -62,6 +62,13 @@ type S3 struct {
}
// URL constructs an S3 request URL based on the current configuration.
//
// Note that the path will be URL escaped based on the AWS [UriEncode rules]
// for broader compatibility with some providers that expect the same
// path format as the one in the canonical signed header
// (see also https://github.com/pocketbase/pocketbase/issues/7153).
//
// [UriEncode rules]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html
func (s3 *S3) URL(path string) string {
scheme := "https"
endpoint := strings.TrimRight(s3.Endpoint, "/")
@@ -72,6 +79,23 @@ func (s3 *S3) URL(path string) string {
scheme = "http"
}
// to prevent double escaping we first parse/unescape it
parsed, err := url.Parse(path)
if err != nil {
// truly rare case, keep the path as it is
} else {
path = escapePath(parsed.Path)
// the rest is usually not expected to be part of the S3 path but it is kept to avoid surprises
// (it will be further escaped if necessery by the Go HTTP client)
if parsed.RawQuery != "" {
path += "?" + parsed.RawQuery
}
if parsed.RawFragment != "" {
path += "#" + parsed.RawFragment
}
}
path = strings.TrimLeft(path, "/")
if s3.UsePathStyle {