s3api: preserve equals signs in tag values (#10058)

* s3api: preserve equals signs in tag values

* s3api: decode tag key once in parseTagsHeader

---------

Co-authored-by: Chris Lu <chris.lu@gmail.com>
This commit is contained in:
patrick
2026-06-23 16:25:32 +08:00
committed by GitHub
parent 16c3f5c816
commit 4bcd27fb6f
2 changed files with 22 additions and 19 deletions
+13 -19
View File
@@ -53,26 +53,20 @@ func FromTags(tags map[string]string) (t *Tagging) {
func parseTagsHeader(tags string) (map[string]string, error) {
parsedTags := make(map[string]string)
for _, v := range util.StringSplit(tags, "&") {
tag := strings.Split(v, "=")
if len(tag) == 2 {
// URL decode both key and value
decodedKey, err := url.QueryUnescape(tag[0])
if err != nil {
return nil, fmt.Errorf("failed to decode tag key '%s': %w", tag[0], err)
}
decodedValue, err := url.QueryUnescape(tag[1])
if err != nil {
return nil, fmt.Errorf("failed to decode tag value '%s': %w", tag[1], err)
}
parsedTags[decodedKey] = decodedValue
} else if len(tag) == 1 {
// URL decode key for empty value tags
decodedKey, err := url.QueryUnescape(tag[0])
if err != nil {
return nil, fmt.Errorf("failed to decode tag key '%s': %w", tag[0], err)
}
parsedTags[decodedKey] = ""
key, value, hasValue := strings.Cut(v, "=")
decodedKey, err := url.QueryUnescape(key)
if err != nil {
return nil, fmt.Errorf("failed to decode tag key '%s': %w", key, err)
}
if !hasValue {
parsedTags[decodedKey] = ""
continue
}
decodedValue, err := url.QueryUnescape(value)
if err != nil {
return nil, fmt.Errorf("failed to decode tag value '%s': %w", value, err)
}
parsedTags[decodedKey] = decodedValue
}
return parsedTags, nil
}
+9
View File
@@ -71,6 +71,15 @@ func TestParseTagsHeader(t *testing.T) {
},
expectError: false,
},
{
name: "unescaped equals in value",
input: "token=part1=part2&normal=test",
expected: map[string]string{
"token": "part1=part2",
"normal": "test",
},
expectError: false,
},
}
for _, tt := range tests {