forked from TrueCloudLab/frostfs-s3-gw
[#613] Number of bucket tags increased to 50
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
c5d8e12a1c
commit
42d6fc3fc6
6 changed files with 59 additions and 13 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue