]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/rgw/rgw_rest_swift.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / rgw / rgw_rest_swift.cc
index 35e192c150ed350736a819609118c362bd5ac6dc..af672c6685ba4a81a84718f503d6e646510a4f8c 100644 (file)
@@ -6,7 +6,7 @@
 #include <boost/optional.hpp>
 #include <boost/utility/in_place_factory.hpp>
 
-#include "include/assert.h"
+#include "include/ceph_assert.h"
 #include "ceph_ver.h"
 
 #include "common/Formatter.h"
 #include "rgw_request.h"
 #include "rgw_process.h"
 
+#include "rgw_zone.h"
+
+#include "services/svc_zone.h"
+
 #include <array>
 #include <sstream>
 #include <memory>
@@ -80,7 +84,7 @@ int RGWListBuckets_ObjStore_SWIFT::get_params()
 
 static void dump_account_metadata(struct req_state * const s,
                                   const RGWUsageStats& global_stats,
-                                  const std::map<std::string, RGWUsageStats> policies_stats,
+                                  const std::map<std::string, RGWUsageStats> &policies_stats,
                                   /* const */map<string, bufferlist>& attrs,
                                   const RGWQuotaInfo& quota,
                                   const RGWAccessControlPolicy_SWIFTAcct &policy)
@@ -174,6 +178,7 @@ void RGWListBuckets_ObjStore_SWIFT::send_response_begin(bool has_buckets)
             user_quota,
             static_cast<RGWAccessControlPolicy_SWIFTAcct&>(*s->user_acl));
     dump_errno(s);
+    dump_header(s, "Accept-Ranges", "bytes");
     end_header(s, NULL, NULL, NO_CONTENT_LENGTH, true);
   }
 
@@ -467,9 +472,10 @@ static void dump_container_metadata(struct req_state *s,
     if (write_acl.size()) {
       dump_header(s, "X-Container-Write", write_acl);
     }
-    if (!s->bucket_info.placement_rule.empty()) {
-      dump_header(s, "X-Storage-Policy", s->bucket_info.placement_rule);
+    if (!s->bucket_info.placement_rule.name.empty()) {
+      dump_header(s, "X-Storage-Policy", s->bucket_info.placement_rule.name);
     }
+    dump_header(s, "X-Storage-Class", s->bucket_info.placement_rule.get_storage_class());
 
     /* Dump user-defined metadata items and generic attrs. */
     const size_t PREFIX_LEN = sizeof(RGW_ATTR_META_PREFIX) - 1;
@@ -529,6 +535,10 @@ static void dump_container_metadata(struct req_state *s,
   if (ws_conf.listing_enabled) {
     dump_header(s, "X-Container-Meta-Web-Listings", "true");
   }
+
+  /* Dump bucket's modification time. Compliance with the Swift API really
+   * needs that. */
+  dump_last_modified(s, s->bucket_mtime);
 }
 
 void RGWStatAccount_ObjStore_SWIFT::execute()
@@ -700,10 +710,10 @@ int RGWCreateBucket_ObjStore_SWIFT::get_params()
     policy.create_default(s->user->user_id, s->user->display_name);
   }
 
-  location_constraint = store->get_zonegroup().api_name;
+  location_constraint = store->svc.zone->get_zonegroup().api_name;
   get_rmattrs_from_headers(s, CONT_PUT_ATTR_PREFIX,
                            CONT_REMOVE_ATTR_PREFIX, rmattr_names);
-  placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
+  placement_rule.init(s->info.env->get("HTTP_X_STORAGE_POLICY", ""), s->info.storage_class);
 
   return get_swift_versioning_settings(s, swift_ver_location);
 }
@@ -715,13 +725,13 @@ static inline int handle_metadata_errors(req_state* const s, const int op_ret)
      * (stored as xattr) size. */
     const auto error_message = boost::str(
       boost::format("Metadata value longer than %lld")
-        % s->cct->_conf->get_val<size_t>("rgw_max_attr_size"));
+        % s->cct->_conf.get_val<Option::size_t>("rgw_max_attr_size"));
     set_req_state_err(s, EINVAL, error_message);
     return -EINVAL;
   } else if (op_ret == -E2BIG) {
     const auto error_message = boost::str(
       boost::format("Too many metadata items; max %lld")
-        % s->cct->_conf->get_val<size_t>("rgw_max_attrs_num_in_req"));
+        % s->cct->_conf.get_val<uint64_t>("rgw_max_attrs_num_in_req"));
     set_req_state_err(s, EINVAL, error_message);
     return -EINVAL;
   }
@@ -813,6 +823,93 @@ int RGWPutObj_ObjStore_SWIFT::verify_permission()
   }
 }
 
+int RGWPutObj_ObjStore_SWIFT::update_slo_segment_size(rgw_slo_entry& entry) {
+
+  int r = 0;
+  const string& path = entry.path;
+
+  /* If the path starts with slashes, strip them all. */
+  const size_t pos_init = path.find_first_not_of('/');
+
+  if (pos_init == string::npos) {
+    return -EINVAL;
+  }
+
+  const size_t pos_sep = path.find('/', pos_init);
+  if (pos_sep == string::npos) {
+    return -EINVAL;
+  }
+
+  string bucket_name = path.substr(pos_init, pos_sep - pos_init);
+  string obj_name = path.substr(pos_sep + 1);
+
+  rgw_bucket bucket;
+
+  if (bucket_name.compare(s->bucket.name) != 0) {
+    RGWBucketInfo bucket_info;
+    map<string, bufferlist> bucket_attrs;
+    auto obj_ctx = store->svc.sysobj->init_obj_ctx();
+    r = store->get_bucket_info(obj_ctx, s->user->user_id.tenant,
+                              bucket_name, bucket_info, nullptr,
+                              &bucket_attrs);
+    if (r < 0) {
+      ldpp_dout(this, 0) << "could not get bucket info for bucket="
+                        << bucket_name << dendl;
+      return r;
+    }
+    bucket = bucket_info.bucket;
+  } else {
+    bucket = s->bucket;
+  }
+
+  /* fetch the stored size of the seg (or error if not valid) */
+  rgw_obj_key slo_key(obj_name);
+  rgw_obj slo_seg(bucket, slo_key);
+
+  /* no prefetch */
+  RGWObjectCtx obj_ctx(store);
+  obj_ctx.set_atomic(slo_seg);
+
+  RGWRados::Object op_target(store, s->bucket_info, obj_ctx, slo_seg);
+  RGWRados::Object::Read read_op(&op_target);
+
+  bool compressed;
+  RGWCompressionInfo cs_info;
+  map<std::string, buffer::list> attrs;
+  uint64_t size_bytes{0};
+
+  read_op.params.attrs = &attrs;
+  read_op.params.obj_size = &size_bytes;
+
+  r = read_op.prepare();
+  if (r < 0) {
+    return r;
+  }
+
+  r = rgw_compression_info_from_attrset(attrs, compressed, cs_info);
+  if (r < 0) {
+    return -EIO;
+  }
+
+  if (compressed) {
+    size_bytes = cs_info.orig_size;
+  }
+
+  /* "When the PUT operation sees the multipart-manifest=put query
+   * parameter, it reads the request body and verifies that each
+   * segment object exists and that the sizes and ETags match. If
+   * there is a mismatch, the PUT operation fails."
+   */
+  if (entry.size_bytes &&
+      (entry.size_bytes != size_bytes)) {
+    return -EINVAL;
+  }
+
+  entry.size_bytes = size_bytes;
+
+  return 0;
+} /* RGWPutObj_ObjStore_SWIFT::update_slo_segment_sizes */
+
 int RGWPutObj_ObjStore_SWIFT::get_params()
 {
   if (s->has_bad_meta) {
@@ -875,7 +972,8 @@ int RGWPutObj_ObjStore_SWIFT::get_params()
     
     slo_info = new RGWSLOInfo;
     
-    int r = rgw_rest_get_json_input_keep_data(s->cct, s, slo_info->entries, max_len, &slo_info->raw_data, &slo_info->raw_data_len);
+    int r = 0;
+    std::tie(r, slo_info->raw_data) = rgw_rest_get_json_input_keep_data(s->cct, s, slo_info->entries, max_len);
     if (r < 0) {
       ldout(s->cct, 5) << "failed to read input for slo r=" << r << dendl;
       return r;
@@ -888,9 +986,21 @@ int RGWPutObj_ObjStore_SWIFT::get_params()
 
     MD5 etag_sum;
     uint64_t total_size = 0;
-    for (const auto& entry : slo_info->entries) {
-      etag_sum.Update((const byte *)entry.etag.c_str(),
+    for (auto& entry : slo_info->entries) {
+      etag_sum.Update((const unsigned char *)entry.etag.c_str(),
                       entry.etag.length());
+
+      /* if size_bytes == 0, it should be replaced with the
+       * real segment size (which could be 0);  this follows from the
+       * fact that Swift requires all segments to exist, but permits
+       * the size_bytes element to be omitted from the SLO manifest, see
+       * https://docs.openstack.org/swift/latest/api/large_objects.html
+       */
+      r = update_slo_segment_size(entry);
+      if (r < 0) {
+       return r;
+      }
+
       total_size += entry.size_bytes;
 
       ldout(s->cct, 20) << "slo_part: " << entry.path
@@ -901,7 +1011,7 @@ int RGWPutObj_ObjStore_SWIFT::get_params()
     complete_etag(etag_sum, &lo_etag);
     slo_info->total_size = total_size;
 
-    ofs = slo_info->raw_data_len;
+    ofs = slo_info->raw_data.length();
   }
 
   return RGWPutObj_ObjStore::get_params();
@@ -1017,7 +1127,7 @@ int RGWPutMetadataBucket_ObjStore_SWIFT::get_params()
 
   get_rmattrs_from_headers(s, CONT_PUT_ATTR_PREFIX, CONT_REMOVE_ATTR_PREFIX,
                           rmattr_names);
-  placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
+  placement_rule.init(s->info.env->get("HTTP_X_STORAGE_POLICY", ""), s->info.storage_class);
 
   return get_swift_versioning_settings(s, swift_ver_location);
 }
@@ -1052,7 +1162,6 @@ int RGWPutMetadataObject_ObjStore_SWIFT::get_params()
     return r;
   }
 
-  placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
   dlo_manifest = s->info.env->get("HTTP_X_OBJECT_MANIFEST");
 
   return 0;
@@ -1205,12 +1314,12 @@ static void get_contype_from_attrs(map<string, bufferlist>& attrs,
 {
   map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_CONTENT_TYPE);
   if (iter != attrs.end()) {
-    content_type = iter->second.c_str();
+    content_type = rgw_bl_str(iter->second);
   }
 }
 
 static void dump_object_metadata(struct req_state * const s,
-                                map<string, bufferlist> attrs)
+                                const map<string, bufferlist>& attrs)
 {
   map<string, string> response_attrs;
 
@@ -1219,9 +1328,9 @@ static void dump_object_metadata(struct req_state * const s,
     const auto aiter = rgw_to_http_attrs.find(name);
 
     if (aiter != std::end(rgw_to_http_attrs)) {
-      response_attrs[aiter->second] = kv.second.c_str();
+      response_attrs[aiter->second] = rgw_bl_str(kv.second);
     } else if (strcmp(name, RGW_ATTR_SLO_UINDICATOR) == 0) {
-      // this attr has an extra length prefix from ::encode() in prior versions
+      // this attr has an extra length prefix from encode() in prior versions
       dump_header(s, "X-Object-Meta-Static-Large-Object", "True");
     } else if (strncmp(name, RGW_ATTR_META_PREFIX,
                       sizeof(RGW_ATTR_META_PREFIX)-1) == 0) {
@@ -1253,7 +1362,7 @@ static void dump_object_metadata(struct req_state * const s,
   if (iter != std::end(attrs)) {
     utime_t delete_at;
     try {
-      ::decode(delete_at, iter->second);
+      decode(delete_at, iter->second);
       if (!delete_at.is_zero()) {
         dump_header(s, "X-Delete-At", delete_at.sec());
       }
@@ -1441,7 +1550,7 @@ int RGWGetObj_ObjStore_SWIFT::send_response_data(bufferlist& bl,
     } else {
       auto iter = attrs.find(RGW_ATTR_ETAG);
       if (iter != attrs.end()) {
-        dump_etag(s, iter->second);
+        dump_etag(s, iter->second.to_str());
       }
     }
 
@@ -1693,7 +1802,7 @@ void RGWGetCrossDomainPolicy_ObjStore_SWIFT::send_response()
      << R"(<!DOCTYPE cross-domain-policy SYSTEM )"
      << R"("http://www.adobe.com/xml/dtds/cross-domain-policy.dtd" >)" << "\n"
      << R"(<cross-domain-policy>)" << "\n"
-     << g_conf->rgw_cross_domain_policy << "\n"
+     << g_conf()->rgw_cross_domain_policy << "\n"
      << R"(</cross-domain-policy>)";
 
   dump_body(s, ss.str());
@@ -1747,7 +1856,7 @@ void RGWInfo_ObjStore_SWIFT::execute()
       s->formatter->close_section();
     }
     else {
-      pair.second.list_data(*(s->formatter), *(s->cct->_conf), *store);
+      pair.second.list_data(*(s->formatter), s->cct->_conf, *store);
     }
   }
 
@@ -1766,41 +1875,41 @@ void RGWInfo_ObjStore_SWIFT::send_response()
 }
 
 void RGWInfo_ObjStore_SWIFT::list_swift_data(Formatter& formatter,
-                                              const md_config_t& config,
+                                              const ConfigProxy& config,
                                               RGWRados& store)
 {
   formatter.open_object_section("swift");
-  formatter.dump_int("max_file_size", config.rgw_max_put_size);
+  formatter.dump_int("max_file_size", config->rgw_max_put_size);
   formatter.dump_int("container_listing_limit", RGW_LIST_BUCKETS_LIMIT_MAX);
 
   string ceph_version(CEPH_GIT_NICE_VER);
   formatter.dump_string("version", ceph_version);
 
   const size_t max_attr_name_len = \
-    g_conf->get_val<size_t>("rgw_max_attr_name_len");
+    g_conf().get_val<Option::size_t>("rgw_max_attr_name_len");
   if (max_attr_name_len) {
     const size_t meta_name_limit = \
       max_attr_name_len - strlen(RGW_ATTR_PREFIX RGW_AMZ_META_PREFIX);
     formatter.dump_int("max_meta_name_length", meta_name_limit);
   }
 
-  const size_t meta_value_limit = g_conf->get_val<size_t>("rgw_max_attr_size");
+  const size_t meta_value_limit = g_conf().get_val<Option::size_t>("rgw_max_attr_size");
   if (meta_value_limit) {
     formatter.dump_int("max_meta_value_length", meta_value_limit);
   }
 
   const size_t meta_num_limit = \
-    g_conf->get_val<size_t>("rgw_max_attrs_num_in_req");
+    g_conf().get_val<uint64_t>("rgw_max_attrs_num_in_req");
   if (meta_num_limit) {
     formatter.dump_int("max_meta_count", meta_num_limit);
   }
 
   formatter.open_array_section("policies");
-  RGWZoneGroup& zonegroup = store.get_zonegroup();
+  const RGWZoneGroup& zonegroup = store.svc.zone->get_zonegroup();
 
   for (const auto& placement_targets : zonegroup.placement_targets) {
     formatter.open_object_section("policy");
-    if (placement_targets.second.name.compare(zonegroup.default_placement) == 0)
+    if (placement_targets.second.name.compare(zonegroup.default_placement.name) == 0)
       formatter.dump_bool("default", true);
     formatter.dump_string("name", placement_targets.second.name.c_str());
     formatter.close_section();
@@ -1814,7 +1923,7 @@ void RGWInfo_ObjStore_SWIFT::list_swift_data(Formatter& formatter,
 }
 
 void RGWInfo_ObjStore_SWIFT::list_tempauth_data(Formatter& formatter,
-                                                 const md_config_t& config,
+                                                 const ConfigProxy& config,
                                                  RGWRados& store)
 {
   formatter.open_object_section("tempauth");
@@ -1822,7 +1931,7 @@ void RGWInfo_ObjStore_SWIFT::list_tempauth_data(Formatter& formatter,
   formatter.close_section();
 }
 void RGWInfo_ObjStore_SWIFT::list_tempurl_data(Formatter& formatter,
-                                                const md_config_t& config,
+                                                const ConfigProxy& config,
                                                 RGWRados& store)
 {
   formatter.open_object_section("tempurl");
@@ -1837,11 +1946,11 @@ void RGWInfo_ObjStore_SWIFT::list_tempurl_data(Formatter& formatter,
 }
 
 void RGWInfo_ObjStore_SWIFT::list_slo_data(Formatter& formatter,
-                                            const md_config_t& config,
+                                            const ConfigProxy& config,
                                             RGWRados& store)
 {
   formatter.open_object_section("slo");
-  formatter.dump_int("max_manifest_segments", config.rgw_max_slo_entries);
+  formatter.dump_int("max_manifest_segments", config->rgw_max_slo_entries);
   formatter.close_section();
 }
 
@@ -1996,7 +2105,7 @@ void RGWFormPost::get_owner_info(const req_state* const s,
 
   /* Need to get user info of bucket owner. */
   RGWBucketInfo bucket_info;
-  int ret = store->get_bucket_info(*static_cast<RGWObjectCtx *>(s->obj_ctx),
+  int ret = store->get_bucket_info(*s->sysobj_ctx,
                                    bucket_tenant, bucket_name,
                                    bucket_info, nullptr);
   if (ret < 0) {
@@ -2030,7 +2139,7 @@ int RGWFormPost::get_params()
       return ret;
     }
 
-    if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
+    if (s->cct->_conf->subsys.should_gather<ceph_subsys_rgw, 20>()) {
       ldout(s->cct, 20) << "read part header -- part.name="
                         << part.name << dendl;
 
@@ -2315,7 +2424,7 @@ RGWOp* RGWSwiftWebsiteHandler::get_ws_redirect_op()
   class RGWMovedPermanently: public RGWOp {
     const std::string location;
   public:
-    RGWMovedPermanently(const std::string& location)
+    explicit RGWMovedPermanently(const std::string& location)
       : location(location) {
     }
 
@@ -2336,7 +2445,7 @@ RGWOp* RGWSwiftWebsiteHandler::get_ws_redirect_op()
       end_header(s, this);
     }
 
-    const string name() override {
+    const char* name() const override {
       return "RGWMovedPermanently";
     }
   };
@@ -2416,7 +2525,7 @@ RGWOp* RGWSwiftWebsiteHandler::get_ws_listing_op()
   public:
     /* Taking prefix_override by value to leverage std::string r-value ref
      * ctor and thus avoid extra memory copying/increasing ref counter. */
-    RGWWebsiteListing(std::string prefix_override)
+    explicit RGWWebsiteListing(std::string prefix_override)
       : prefix_override(std::move(prefix_override)) {
     }
   };
@@ -2442,8 +2551,8 @@ bool RGWSwiftWebsiteHandler::is_web_dir() const
 
   /* First, get attrset of the object we'll try to retrieve. */
   RGWObjectCtx& obj_ctx = *static_cast<RGWObjectCtx *>(s->obj_ctx);
-  obj_ctx.obj.set_atomic(obj);
-  obj_ctx.obj.set_prefetch_data(obj);
+  obj_ctx.set_atomic(obj);
+  obj_ctx.set_prefetch_data(obj);
 
   RGWObjState* state = nullptr;
   if (store->get_obj_state(&obj_ctx, s->bucket_info, obj, &state, false) < 0) {
@@ -2472,8 +2581,8 @@ bool RGWSwiftWebsiteHandler::is_index_present(const std::string& index)
   rgw_obj obj(s->bucket, index);
 
   RGWObjectCtx& obj_ctx = *static_cast<RGWObjectCtx *>(s->obj_ctx);
-  obj_ctx.obj.set_atomic(obj);
-  obj_ctx.obj.set_prefetch_data(obj);
+  obj_ctx.set_atomic(obj);
+  obj_ctx.set_prefetch_data(obj);
 
   RGWObjState* state = nullptr;
   if (store->get_obj_state(&obj_ctx, s->bucket_info, obj, &state, false) < 0) {
@@ -2671,9 +2780,9 @@ RGWOp *RGWHandler_REST_Obj_SWIFT::op_options()
 }
 
 
-int RGWHandler_REST_SWIFT::authorize()
+int RGWHandler_REST_SWIFT::authorize(const DoutPrefixProvider *dpp)
 {
-  return rgw::auth::Strategy::apply(auth_strategy, s);
+  return rgw::auth::Strategy::apply(dpp, auth_strategy, s);
 }
 
 int RGWHandler_REST_SWIFT::postauth_init()
@@ -2755,6 +2864,8 @@ int RGWHandler_REST_SWIFT::validate_bucket_name(const string& bucket)
   for (size_t i = 0; i < len; ++i, ++s) {
     if (*(unsigned char *)s == 0xff)
       return -ERR_INVALID_BUCKET_NAME;
+    if (*(unsigned char *)s == '/')
+      return -ERR_INVALID_BUCKET_NAME;
   }
 
   return 0;
@@ -2807,23 +2918,23 @@ int RGWHandler_REST_SWIFT::init_from_header(struct req_state* const s,
   }
 
   if ('\0' == req_name[0]) {
-    return g_conf->rgw_swift_url_prefix == "/" ? -ERR_BAD_URL : 0;
+    return g_conf()->rgw_swift_url_prefix == "/" ? -ERR_BAD_URL : 0;
   }
 
   req = req_name;
 
   size_t pos = req.find('/');
-  if (std::string::npos != pos && g_conf->rgw_swift_url_prefix != "/") {
-    bool cut_url = g_conf->rgw_swift_url_prefix.length();
+  if (std::string::npos != pos && g_conf()->rgw_swift_url_prefix != "/") {
+    bool cut_url = g_conf()->rgw_swift_url_prefix.length();
     first = req.substr(0, pos);
 
-    if (first.compare(g_conf->rgw_swift_url_prefix) == 0) {
+    if (first.compare(g_conf()->rgw_swift_url_prefix) == 0) {
       if (cut_url) {
         /* Rewind to the "v1/..." part. */
         next_tok(req, first, '/');
       }
     }
-  } else if (req.compare(g_conf->rgw_swift_url_prefix) == 0) {
+  } else if (req.compare(g_conf()->rgw_swift_url_prefix) == 0) {
     s->formatter = new RGWFormatter_Plain;
     return -ERR_BAD_URL;
   } else {
@@ -2831,19 +2942,19 @@ int RGWHandler_REST_SWIFT::init_from_header(struct req_state* const s,
   }
 
   std::string tenant_path;
-  if (! g_conf->rgw_swift_tenant_name.empty()) {
+  if (! g_conf()->rgw_swift_tenant_name.empty()) {
     tenant_path = "/AUTH_";
-    tenant_path.append(g_conf->rgw_swift_tenant_name);
+    tenant_path.append(g_conf()->rgw_swift_tenant_name);
   }
 
   /* verify that the request_uri conforms with what's expected */
-  char buf[g_conf->rgw_swift_url_prefix.length() + 16 + tenant_path.length()];
+  char buf[g_conf()->rgw_swift_url_prefix.length() + 16 + tenant_path.length()];
   int blen;
-  if (g_conf->rgw_swift_url_prefix == "/") {
+  if (g_conf()->rgw_swift_url_prefix == "/") {
     blen = sprintf(buf, "/v1%s", tenant_path.c_str());
   } else {
     blen = sprintf(buf, "/%s/v1%s",
-                   g_conf->rgw_swift_url_prefix.c_str(), tenant_path.c_str());
+                   g_conf()->rgw_swift_url_prefix.c_str(), tenant_path.c_str());
   }
 
   if (strncmp(reqbuf, buf, blen) != 0) {
@@ -2858,7 +2969,7 @@ int RGWHandler_REST_SWIFT::init_from_header(struct req_state* const s,
 
   next_tok(req, ver, '/');
 
-  if (!tenant_path.empty() || g_conf->rgw_swift_account_in_url) {
+  if (!tenant_path.empty() || g_conf()->rgw_swift_account_in_url) {
     string account_name;
     next_tok(req, account_name, '/');
 
@@ -2941,6 +3052,8 @@ int RGWHandler_REST_SWIFT::init(RGWRados* store, struct req_state* s,
     s->op = OP_PUT;
   }
 
+  s->info.storage_class = s->info.env->get("HTTP_X_OBJECT_STORAGE_CLASS", "");
+
   return RGWHandler_REST::init(store, s, cio);
 }