[#613] Number of bucket tags increased to 50

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
Denis Kirillov 2025-03-27 16:10:33 +03:00
parent c5d8e12a1c
commit 42d6fc3fc6
6 changed files with 59 additions and 13 deletions

View file

@ -4,6 +4,9 @@ This document outlines major changes between releases.
## [Unreleased]
### Fixed
- Number of bucket tags increased to 50 (#613)
## [0.32.13] - 2025-03-10
### Fixed

View file

@ -153,7 +153,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
}
if args.TaggingDirective == replaceDirective {
tagSet, err = parseTaggingHeader(r.Header)
tagSet, err = parseObjectTaggingHeader(r.Header)
if err != nil {
h.logAndSendError(ctx, w, "could not parse tagging header", reqInfo, err)
return

View file

@ -134,7 +134,7 @@ func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Re
}
if len(r.Header.Get(api.AmzTagging)) > 0 {
p.Data.TagSet, err = parseTaggingHeader(r.Header)
p.Data.TagSet, err = parseObjectTaggingHeader(r.Header)
if err != nil {
h.logAndSendError(ctx, w, "could not parse tagging", reqInfo, err, additional...)
return

View file

@ -222,7 +222,7 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
return
}
tagSet, err := parseTaggingHeader(r.Header)
tagSet, err := parseObjectTaggingHeader(r.Header)
if err != nil {
h.logAndSendError(ctx, w, "could not parse tagging header", reqInfo, err)
return
@ -511,7 +511,7 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
fmt.Errorf("%w: %s", apierr.GetAPIError(apierr.ErrMalformedXML), err.Error()))
return
}
tagSet, err = h.readTagSet(tags)
tagSet, err = readObjectTagSet(tags)
if err != nil {
h.logAndSendError(ctx, w, "could not read tag set", reqInfo, err)
return
@ -742,14 +742,14 @@ func aclHeadersStatus(r *http.Request) aclStatus {
return aclStatusNo
}
func parseTaggingHeader(header http.Header) (map[string]string, error) {
func parseObjectTaggingHeader(header http.Header) (map[string]string, error) {
var tagSet map[string]string
if tagging := header.Get(api.AmzTagging); len(tagging) > 0 {
queries, err := url.ParseQuery(tagging)
if err != nil {
return nil, apierr.GetAPIError(apierr.ErrInvalidArgument)
}
if len(queries) > maxTags {
if len(queries) > maxObjectTags {
return nil, apierr.GetAPIError(apierr.ErrInvalidTagsSizeExceed)
}
tagSet = make(map[string]string, len(queries))

View file

@ -16,7 +16,8 @@ import (
const (
allowedTagChars = "+-=._:/@"
maxTags = 10
maxObjectTags = 10
maxBucketTags = 50
keyTagMaxLength = 128
valueTagMaxLength = 256
)
@ -27,7 +28,7 @@ func (h *handler) PutObjectTaggingHandler(w http.ResponseWriter, r *http.Request
reqInfo := middleware.GetReqInfo(ctx)
tagSet, err := h.readTagSet(reqInfo.Tagging)
tagSet, err := readObjectTagSet(reqInfo.Tagging)
if err != nil {
h.logAndSendError(ctx, w, "could not read tag set", reqInfo, err)
return
@ -128,7 +129,7 @@ func (h *handler) PutBucketTaggingHandler(w http.ResponseWriter, r *http.Request
reqInfo := middleware.GetReqInfo(ctx)
tagSet, err := h.readTagSet(reqInfo.Tagging)
tagSet, err := readBucketTagSet(reqInfo.Tagging)
if err != nil {
h.logAndSendError(ctx, w, "could not read tag set", reqInfo, err)
return
@ -194,8 +195,16 @@ func (h *handler) DeleteBucketTaggingHandler(w http.ResponseWriter, r *http.Requ
w.WriteHeader(http.StatusNoContent)
}
func (h *handler) readTagSet(tagging *data.Tagging) (map[string]string, error) {
if err := checkTagSet(tagging.TagSet); err != nil {
func readObjectTagSet(tagging *data.Tagging) (map[string]string, error) {
return readTagSetBase(tagging, maxObjectTags)
}
func readBucketTagSet(tagging *data.Tagging) (map[string]string, error) {
return readTagSetBase(tagging, maxBucketTags)
}
func readTagSetBase(tagging *data.Tagging, maxTags int) (map[string]string, error) {
if err := checkTagSet(tagging.TagSet, maxTags); err != nil {
return nil, err
}
@ -222,7 +231,7 @@ func encodeTagging(tagSet map[string]string) *data.Tagging {
return tagging
}
func checkTagSet(tagSet []data.Tag) error {
func checkTagSet(tagSet []data.Tag, maxTags int) error {
if len(tagSet) > maxTags {
return errors.GetAPIError(errors.ErrInvalidTagsSizeExceed)
}

View file

@ -3,6 +3,7 @@ package handler
import (
"net/http"
"net/http/httptest"
"strconv"
"strings"
"testing"
@ -131,7 +132,40 @@ func TestGetBucketTagging(t *testing.T) {
getBucketTaggingErr(hc, bktName, apierr.GetAPIError(apierr.ErrNoSuchTagSet))
}
func TestPutBucketTaggingLimit(t *testing.T) {
hc := prepareHandlerContext(t)
bktName := "bucket"
createBucket(hc, bktName)
tagsLen := 51
tags := make(map[string]string, tagsLen)
for i := 0; i < tagsLen; i++ {
tags["key"+strconv.Itoa(i)] = "val"
}
putBucketTaggingErr(hc, bktName, tags, apierr.ErrInvalidTagsSizeExceed)
delete(tags, "key0")
putBucketTagging(hc, bktName, tags)
tagSet := getBucketTagging(hc, bktName)
require.Len(t, tagSet.TagSet, 50)
putBucketTagging(hc, bktName, nil)
getBucketTaggingErr(hc, bktName, apierr.GetAPIError(apierr.ErrNoSuchTagSet))
}
func putBucketTagging(hc *handlerContext, bktName string, tags map[string]string) {
w := putBucketTaggingBase(hc, bktName, tags)
assertStatus(hc.t, w, http.StatusOK)
}
func putBucketTaggingErr(hc *handlerContext, bktName string, tags map[string]string, errCode apierr.ErrorCode) {
w := putBucketTaggingBase(hc, bktName, tags)
assertS3Error(hc.t, w, apierr.GetAPIError(errCode))
}
func putBucketTaggingBase(hc *handlerContext, bktName string, tags map[string]string) *httptest.ResponseRecorder {
body := &data.Tagging{
TagSet: make([]data.Tag, 0, len(tags)),
}
@ -146,7 +180,7 @@ func putBucketTagging(hc *handlerContext, bktName string, tags map[string]string
w, r := prepareTestRequest(hc, bktName, "", body)
middleware.GetReqInfo(r.Context()).Tagging = body
hc.Handler().PutBucketTaggingHandler(w, r)
assertStatus(hc.t, w, http.StatusOK)
return w
}
func getBucketTagging(hc *handlerContext, bktName string) *data.Tagging {