From 2a4d8a61ca5485fea7fee7a57465be7dcbb4557d Mon Sep 17 00:00:00 2001 From: Dmytro Iurchenko Date: Tue, 3 Feb 2015 17:54:38 +0200 Subject: [PATCH] rgw: Swift API. Support for X-Remove-Container-Meta-{key} header. Fixes: #10475 Backport: hammer, firefly Reported-by: Josh Durgin Signed-off-by: Dmytro Iurchenko (cherry picked from commit f67bfa24fd6f69c2fcc0987eba8b6b426dd78320) Conflicts: src/rgw/rgw_rest.h trivial merge: prototype of an unrelated function changed --- src/rgw/rgw_common.h | 2 +- src/rgw/rgw_op.cc | 17 +++++++++++-- src/rgw/rgw_op.h | 3 ++- src/rgw/rgw_rest.cc | 50 ++++++++++++++++++++++++++++----------- src/rgw/rgw_rest.h | 2 ++ src/rgw/rgw_rest_swift.cc | 23 ++++++++++++++++++ 6 files changed, 79 insertions(+), 18 deletions(-) diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 432e82a39790c6..975bb9dbc63dff 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -849,7 +849,7 @@ struct req_info { req_info(CephContext *cct, RGWEnv *_env); void rebuild_from(req_info& src); - void init_meta_info(bool *found_nad_meta); + void init_meta_info(bool *found_bad_meta); }; /** Store all the state necessary to complete and respond to an HTTP request*/ diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 4cc12eabb3884e..2afd7f4fd9569c 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -1895,11 +1895,24 @@ void RGWPutMetadata::execute() orig_attrs = s->bucket_attrs; } - /* only remove meta attrs */ for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) { const string& name = iter->first; + /* check if the attr is user-defined metadata item */ if (name.compare(0, meta_prefix_len, meta_prefix) == 0) { - rmattrs[name] = iter->second; + if (is_object_op) { + /* for the objects all existing meta attrs have to be removed */ + rmattrs[name] = iter->second; + } else { + /* for the buckets all existing meta attrs are preserved, + except those that are listed in rmattr_names. */ + if (rmattr_names.find(name) != rmattr_names.end()) { + map::iterator aiter = attrs.find(name); + if (aiter != attrs.end()) { + attrs.erase(aiter); + } + rmattrs[name] = iter->second; + } + } } else if (attrs.find(name) == attrs.end()) { attrs[name] = iter->second; } diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index bd6f96401d1ab0..98922f767cc0ea 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -14,6 +14,7 @@ #include #include +#include #include #include "rgw_common.h" @@ -402,7 +403,7 @@ class RGWPostObj : public RGWOp { class RGWPutMetadata : public RGWOp { protected: int ret; - map attrs; + set rmattr_names; bool has_policy, has_cors; RGWAccessControlPolicy policy; RGWCORSConfiguration cors_config; diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index 59026fbc3395dc..a907decf063d5e 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -76,10 +76,10 @@ string lowercase_underscore_http_attr(const string& orig) for (size_t i = 0; i < orig.size(); ++i, ++s) { switch (*s) { case '-': - buf[i] = '_'; - break; + buf[i] = '_'; + break; default: - buf[i] = tolower(*s); + buf[i] = tolower(*s); } } return string(buf); @@ -98,10 +98,32 @@ string uppercase_underscore_http_attr(const string& orig) for (size_t i = 0; i < orig.size(); ++i, ++s) { switch (*s) { case '-': - buf[i] = '_'; - break; + buf[i] = '_'; + break; default: - buf[i] = toupper(*s); + buf[i] = toupper(*s); + } + } + return string(buf); +} + +/* + * make attrs look-like-this + * converts underscores to dashes + */ +string lowercase_dash_http_attr(const string& orig) +{ + const char *s = orig.c_str(); + char buf[orig.size() + 1]; + buf[orig.size()] = '\0'; + + for (size_t i = 0; i < orig.size(); ++i, ++s) { + switch (*s) { + case '_': + buf[i] = '-'; + break; + default: + buf[i] = tolower(*s); } } return string(buf); @@ -122,15 +144,15 @@ string camelcase_dash_http_attr(const string& orig) for (size_t i = 0; i < orig.size(); ++i, ++s) { switch (*s) { case '_': - buf[i] = '-'; - last_sep = true; - break; + buf[i] = '-'; + last_sep = true; + break; default: - if (last_sep) - buf[i] = toupper(*s); - else - buf[i] = tolower(*s); - last_sep = false; + if (last_sep) + buf[i] = toupper(*s); + else + buf[i] = tolower(*s); + last_sep = false; } } return string(buf); diff --git a/src/rgw/rgw_rest.h b/src/rgw/rgw_rest.h index d42ec8d1a02a3c..a6108f4e75a7b3 100644 --- a/src/rgw/rgw_rest.h +++ b/src/rgw/rgw_rest.h @@ -12,6 +12,8 @@ extern std::map rgw_to_http_attrs; extern void rgw_rest_init(CephContext *cct); +extern string lowercase_dash_http_attr(const string& orig); + extern void rgw_flush_formatter_and_reset(struct req_state *s, ceph::Formatter *formatter); diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index 36544dbb5bfd40..ab3c142fda5c4b 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -424,6 +424,11 @@ void RGWPutObj_ObjStore_SWIFT::send_response() rgw_flush_formatter_and_reset(s, s->formatter); } +#define REMOVE_ATTR_PREFIX "HTTP_X_REMOVE_CONTAINER_META_" +#define PUT_ATTR_PREFIX "HTTP_X_CONTAINER_META_" +#define REMOVE_ATTR_PREFIX_LEN sizeof(REMOVE_ATTR_PREFIX) - 1 +#define PUT_ATTR_PREFIX_LEN sizeof(PUT_ATTR_PREFIX) - 1 + int RGWPutMetadata_ObjStore_SWIFT::get_params() { if (s->has_bad_meta) @@ -434,6 +439,24 @@ int RGWPutMetadata_ObjStore_SWIFT::get_params() if (r < 0) { return r; } + map& m = s->info.env->get_map(); + map::iterator iter; + for (iter = m.begin(); iter != m.end(); ++iter) { + size_t prefix_len = 0; + const char *p = iter->first.c_str(); + if (strncasecmp(p, REMOVE_ATTR_PREFIX, REMOVE_ATTR_PREFIX_LEN) == 0) { + // Explicitly requested removal + prefix_len = REMOVE_ATTR_PREFIX_LEN; + } else if ((strncasecmp(p, PUT_ATTR_PREFIX, PUT_ATTR_PREFIX_LEN) == 0) && iter->second.empty()) { + // Removal requested by putting an empty value + prefix_len = PUT_ATTR_PREFIX_LEN; + } + if (prefix_len > 0) { + string name(RGW_ATTR_META_PREFIX); + name.append(lowercase_dash_http_attr(p + prefix_len)); + rmattr_names.insert(name); + } + } } return 0;