Fix: some bugs about object tagging and bucket tagging

Signed-off-by: yuboLee <pangbolee@gmail.com>
This commit is contained in:
yuboLee 2020-07-09 13:32:42 +08:00
parent 569da2384b
commit ce4f466f0f
7 changed files with 94 additions and 18 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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
)

View File

@ -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)
}

View File

@ -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

View File

@ -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,

View File

@ -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 {