mirror of
https://github.com/cubefs/cubefs.git
synced 2026-08-02 02:00:56 +00:00
Fix: some bugs about object tagging and bucket tagging
Signed-off-by: yuboLee <pangbolee@gmail.com>
This commit is contained in:
parent
569da2384b
commit
ce4f466f0f
@ -203,12 +203,19 @@ func (o *ObjectNode) getBucketTaggingHandler(w http.ResponseWriter, r *http.Requ
|
||||
var output, _ = ParseTagging(string(ossTaggingData))
|
||||
|
||||
var encoded []byte
|
||||
if encoded, err = MarshalXMLEntity(output); err != nil {
|
||||
log.LogErrorf("getBucketTaggingHandler: encode output fail: requestID(%v) err(%v)", GetRequestID(r), err)
|
||||
_ = InternalErrorCode(err).ServeResponse(w, r)
|
||||
return
|
||||
if nil == output || len(output.TagSet) == 0 {
|
||||
sb := strings.Builder{}
|
||||
sb.WriteString(xml.Header)
|
||||
sb.WriteString("<Tagging></Tagging>")
|
||||
encoded = []byte(sb.String())
|
||||
} else {
|
||||
if encoded, err = MarshalXMLEntity(output); err != nil {
|
||||
log.LogErrorf("getBucketTaggingHandler: encode output fail: requestID(%v) err(%v)", GetRequestID(r), err)
|
||||
_ = InternalErrorCode(err).ServeResponse(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
w.Header()[HeaderNameContentType] = []string{HeaderValueContentTypeXML}
|
||||
if _, err = w.Write(encoded); err != nil {
|
||||
log.LogErrorf("getBucketTaggingHandler: write response fail: requestID(%v) err(%v)", GetRequestID(r), err)
|
||||
}
|
||||
@ -251,8 +258,13 @@ func (o *ObjectNode) putBucketTaggingHandler(w http.ResponseWriter, r *http.Requ
|
||||
_ = InvalidArgument.ServeResponse(w, r)
|
||||
return
|
||||
}
|
||||
validateRes, errorCode := tagging.Validate()
|
||||
if !validateRes {
|
||||
log.LogErrorf("putBucketTaggingHandler: tagging validate fail: requestID(%v) tagging(%v) err(%v)", GetRequestID(r), tagging, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = vol.SetXAttr("/", XAttrKeyOSSTagging, []byte(tagging.Encode())); err != nil {
|
||||
if err = vol.SetXAttr("/", XAttrKeyOSSTagging, []byte(tagging.Encode()), false); err != nil {
|
||||
_ = InternalErrorCode(err).ServeResponse(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
@ -218,6 +218,21 @@ func (o *ObjectNode) getObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||
contentLength = rangeUpper - rangeLower + 1
|
||||
}
|
||||
|
||||
// get object tagging size
|
||||
var xattrInfo *proto.XAttrInfo
|
||||
if xattrInfo, err = vol.GetXAttr(param.object, XAttrKeyOSSTagging); err != nil && err != syscall.ENOENT {
|
||||
log.LogErrorf("getObjectHandler: Volume get XAttr fail: requestID(%v) err(%v)", GetRequestID(r), err)
|
||||
errorCode = InternalErrorCode(err)
|
||||
return
|
||||
}
|
||||
if xattrInfo != nil {
|
||||
ossTaggingData := xattrInfo.Get(XAttrKeyOSSTagging)
|
||||
output, _ := ParseTagging(string(ossTaggingData))
|
||||
if output != nil && len(output.TagSet) > 0 {
|
||||
w.Header()[HeaderNameXAmzTaggingCount] = []string{strconv.Itoa(len(output.TagSet))}
|
||||
}
|
||||
}
|
||||
|
||||
// set response header for GetObject
|
||||
w.Header()[HeaderNameAcceptRange] = []string{HeaderValueAcceptRange}
|
||||
w.Header()[HeaderNameLastModified] = []string{formatTimeRFC1123(fileInfo.ModifyTime)}
|
||||
@ -1097,6 +1112,11 @@ func (o *ObjectNode) putObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||
errorCode = InvalidArgument
|
||||
return
|
||||
}
|
||||
var validateRes bool
|
||||
if validateRes, errorCode = tagging.Validate(); !validateRes {
|
||||
log.LogErrorf("putObjectHandler: tagging validate fail: requestID(%v) tagging(%v) err(%v)", GetRequestID(r), tagging, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Checking user-defined metadata
|
||||
@ -1330,14 +1350,24 @@ func (o *ObjectNode) putObjectTaggingHandler(w http.ResponseWriter, r *http.Requ
|
||||
errorCode = InvalidArgument
|
||||
return
|
||||
}
|
||||
|
||||
if err = vol.SetXAttr(param.object, XAttrKeyOSSTagging, []byte(tagging.Encode())); err != nil {
|
||||
log.LogErrorf("pubObjectTaggingHandler: volume set tagging fail: requestID(%v) volume(%v) object(%v) err(%v)",
|
||||
GetRequestID(r), param.Bucket(), param.Object(), err)
|
||||
errorCode = InternalErrorCode(err)
|
||||
validateRes, errorCode := tagging.Validate()
|
||||
if !validateRes {
|
||||
log.LogErrorf("putObjectTaggingHandler: tagging validate fail: requestID(%v) tagging(%v) err(%v)", GetRequestID(r), tagging, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = vol.SetXAttr(param.object, XAttrKeyOSSTagging, []byte(tagging.Encode()), false);
|
||||
|
||||
if err != nil {
|
||||
log.LogErrorf("pubObjectTaggingHandler: volume set tagging fail: requestID(%v) volume(%v) object(%v) err(%v)",
|
||||
GetRequestID(r), param.Bucket(), param.Object(), err)
|
||||
if err == syscall.ENOENT {
|
||||
errorCode = NoSuchKey
|
||||
} else {
|
||||
errorCode = InternalErrorCode(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -1432,7 +1462,7 @@ func (o *ObjectNode) putObjectXAttrHandler(w http.ResponseWriter, r *http.Reques
|
||||
return
|
||||
}
|
||||
|
||||
if err = vol.SetXAttr(param.object, key, []byte(value)); err != nil {
|
||||
if err = vol.SetXAttr(param.object, key, []byte(value), true); err != nil {
|
||||
if err == syscall.ENOENT {
|
||||
errorCode = NoSuchKey
|
||||
return
|
||||
|
||||
@ -65,6 +65,7 @@ const (
|
||||
HeaderNameXAmzDownloadPartCount = "x-amz-mp-parts-count"
|
||||
HeaderNameXAmzMetadataDirective = "x-amz-metadata-directive"
|
||||
HeaderNameXAmzBucketRegion = "x-amz-bucket-region"
|
||||
HeaderNameXAmzTaggingCount = "x-amz-tagging-count"
|
||||
|
||||
HeaderNameIfMatch = "If-Match"
|
||||
HeaderNameIfNoneMatch = "If-None-Match"
|
||||
@ -165,3 +166,9 @@ const (
|
||||
MetadataDirectiveCopy = "COPY"
|
||||
MetadataDirectiveReplace = "REPLACE"
|
||||
)
|
||||
|
||||
const (
|
||||
TaggingCounts = 10
|
||||
TaggingKeyMaxLength = 128
|
||||
TaggingValueMaxLength = 256
|
||||
)
|
||||
|
||||
@ -61,7 +61,7 @@ func (s *xattrStore) Put(vol, path, key string, data []byte) (err error) {
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
err = v.SetXAttr(path, key, data)
|
||||
err = v.SetXAttr(path, key, data, false)
|
||||
if err != nil {
|
||||
log.LogErrorf("put xattr failed: vol[%v], key[%v], data[%v]", vol, key, data)
|
||||
}
|
||||
|
||||
@ -265,12 +265,15 @@ func (v *Volume) getInodeFromPath(path string) (inode uint64, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (v *Volume) SetXAttr(path string, key string, data []byte) error {
|
||||
func (v *Volume) SetXAttr(path string, key string, data []byte, autoCreate bool) error {
|
||||
var err error
|
||||
var inode uint64
|
||||
if inode, err = v.getInodeFromPath(path); err != nil && err != syscall.ENOENT {
|
||||
return err
|
||||
}
|
||||
if err == syscall.ENOENT && !autoCreate {
|
||||
return err
|
||||
}
|
||||
if err == syscall.ENOENT {
|
||||
var dirs, filename = splitPath(path)
|
||||
var parentID uint64
|
||||
|
||||
@ -16,6 +16,7 @@ package objectnode
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"github.com/chubaofs/chubaofs/util/log"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
@ -235,7 +236,7 @@ type Tag struct {
|
||||
|
||||
type Tagging struct {
|
||||
XMLName xml.Name `json:"-"`
|
||||
TagSet []Tag `xml:"TagSet>Tag" json:"ts"`
|
||||
TagSet []Tag `xml:"TagSet>Tag,omitempty" json:"ts"`
|
||||
}
|
||||
|
||||
func (t Tagging) Encode() string {
|
||||
@ -246,6 +247,23 @@ func (t Tagging) Encode() string {
|
||||
return values.Encode()
|
||||
}
|
||||
|
||||
func (t Tagging) Validate() (bool, *ErrorCode) {
|
||||
var errorCode *ErrorCode
|
||||
if len(t.TagSet) > TaggingCounts {
|
||||
return false, TagsGreaterThen10
|
||||
}
|
||||
for _, tag := range t.TagSet {
|
||||
log.LogDebugf("Validate: key : (%v), value : (%v)", tag.Key, tag.Value)
|
||||
if len(tag.Key) > TaggingKeyMaxLength {
|
||||
return false, InvalidTagKey
|
||||
}
|
||||
if len(tag.Value) > TaggingValueMaxLength {
|
||||
return false, InvalidTagValue
|
||||
}
|
||||
}
|
||||
return true, errorCode
|
||||
}
|
||||
|
||||
func NewTagging() *Tagging {
|
||||
return &Tagging{
|
||||
XMLName: xml.Name{Local: "Tagging"},
|
||||
@ -261,6 +279,9 @@ func ParseTagging(src string) (*Tagging, error) {
|
||||
for key, value := range values {
|
||||
tagSet = append(tagSet, Tag{Key: key, Value: value[0]})
|
||||
}
|
||||
if len(tagSet) == 0 {
|
||||
return NewTagging(), nil
|
||||
}
|
||||
return &Tagging{
|
||||
XMLName: xml.Name{Local: "Tagging"},
|
||||
TagSet: tagSet,
|
||||
|
||||
@ -88,7 +88,7 @@ var (
|
||||
InvalidRange = &ErrorCode{ErrorCode: "InvalidRange", ErrorMessage: "The requested range cannot be satisfied.", StatusCode: http.StatusRequestedRangeNotSatisfiable}
|
||||
MissingContentLength = &ErrorCode{ErrorCode: "MissingContentLength", ErrorMessage: "You must provide the Content-Length HTTP header.", StatusCode: http.StatusLengthRequired}
|
||||
NoSuchBucket = &ErrorCode{ErrorCode: "NoSuchBucket", ErrorMessage: "The specified bucket does not exist.", StatusCode: http.StatusNotFound}
|
||||
NoSuchKey = &ErrorCode{ErrorCode: "NoLoggingStatusForKey", ErrorMessage: "The specified key does not exist.", StatusCode: http.StatusNotFound}
|
||||
NoSuchKey = &ErrorCode{ErrorCode: "NoSuchKey", ErrorMessage: "The specified key does not exist.", StatusCode: http.StatusNotFound}
|
||||
PreconditionFailed = &ErrorCode{ErrorCode: "PreconditionFailed", ErrorMessage: "At least one of the preconditions you specified did not hold.", StatusCode: http.StatusPreconditionFailed}
|
||||
MaxContentLength = &ErrorCode{ErrorCode: "MaxContentLength", ErrorMessage: "Content-Length is bigger than 20KB.", StatusCode: http.StatusLengthRequired}
|
||||
DuplicatedBucket = &ErrorCode{ErrorCode: "CreateBucketFailed", ErrorMessage: "Duplicate bucket name.", StatusCode: http.StatusBadRequest}
|
||||
@ -97,9 +97,12 @@ var (
|
||||
NoSuchUpload = &ErrorCode{ErrorCode: "NoSuchUpload", ErrorMessage: "The specified upload does not exist.", StatusCode: http.StatusNotFound}
|
||||
OverMaxRecordSize = &ErrorCode{ErrorCode: "OverMaxRecordSize", ErrorMessage: "The length of a record in the input or result is greater than maxCharsPerRecord of 1 MB.", StatusCode: http.StatusBadRequest}
|
||||
CopySourceSizeTooLarge = &ErrorCode{ErrorCode: "InvalidRequest", ErrorMessage: "The specified copy source is larger than the maximum allowable size for a copy source: 5368709120", StatusCode: http.StatusBadRequest}
|
||||
InvalidPartOrder = &ErrorCode{ErrorCode: "InvalidPartOrder", ErrorMessage: "The list of parts was not in ascending order. Parts list must be specified in order by part number.", StatusCode: http.StatusBadRequest}
|
||||
InvalidPart = &ErrorCode{ErrorCode: "InvalidPart", ErrorMessage: "One or more of the specified parts could not be found. The part might not have been uploaded, or the specified entity tag might not have matched the part's entity tag.", StatusCode: http.StatusBadRequest}
|
||||
InvalidPartOrder = &ErrorCode{ErrorCode: "InvalidPartOrder", ErrorMessage: "The list of parts was not in ascending order. Parts list must be specified in order by part number.", StatusCode: http.StatusBadRequest}
|
||||
InvalidPart = &ErrorCode{ErrorCode: "InvalidPart", ErrorMessage: "One or more of the specified parts could not be found. The part might not have been uploaded, or the specified entity tag might not have matched the part's entity tag.", StatusCode: http.StatusBadRequest}
|
||||
InvalidCacheArgument = &ErrorCode{ErrorCode: "InvalidCacheArgument", ErrorMessage: "Invalid Cache-Control or Expires Argument", StatusCode: http.StatusBadRequest}
|
||||
TagsGreaterThen10 = &ErrorCode{ErrorCode: "BadRequest", ErrorMessage: "Object tags cannot be greater than 10", StatusCode: http.StatusBadRequest}
|
||||
InvalidTagKey = &ErrorCode{ErrorCode: "InvalidTag", ErrorMessage: "The TagKey you have provided is invalid", StatusCode: http.StatusBadRequest}
|
||||
InvalidTagValue = &ErrorCode{ErrorCode: "InvalidTag", ErrorMessage: "The TagValue you have provided is invalid", StatusCode: http.StatusBadRequest}
|
||||
)
|
||||
|
||||
func HttpStatusErrorCode(code int) *ErrorCode {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user