]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: switch to RGWStreamIO::send_header().
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Wed, 10 Aug 2016 16:17:14 +0000 (18:17 +0200)
committerRadoslaw Zarzynski <rzarzynski@mirantis.com>
Fri, 21 Oct 2016 20:57:20 +0000 (22:57 +0200)
Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
src/rgw/rgw_client_io_decoimpl.h
src/rgw/rgw_rest.cc
src/rgw/rgw_rest.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_swift_auth.cc

index 250ba8c7aba891dba416f9f916c27610196b7a32..d41da6060191450df5b9a6b492945baf72d9306f 100644 (file)
@@ -308,10 +308,8 @@ public:
     size_t sent = 0;
 
     if (! has_content_length) {
-      constexpr char TRANSFER_CHUNKED[] = "Transfer-Enconding: chunked\r\n";
-
-      sent += RGWDecoratedStreamIO<T>::write_data(TRANSFER_CHUNKED,
-                                                  sizeof(TRANSFER_CHUNKED) - 1);
+      sent += RGWDecoratedStreamIO<T>::send_header("Transfer-Enconding",
+                                                   "chunked");
       chunking_enabled = true;
     }
 
index 5990a1536514d3bab141bfff468ec42f9e886b61..c58eb966e47d150a57c41bd7c7ca2166e20dee14 100644 (file)
@@ -369,48 +369,84 @@ void dump_errno(struct req_state *s, int http_ret)
   dump_status(s, http_ret, http_status_names[http_ret]);
 }
 
-void dump_string_header(struct req_state *s, const char *name, const char *val)
+void dump_header(struct req_state* const s,
+                 const boost::string_ref& name,
+                 const boost::string_ref& val)
 {
-  int r = STREAM_IO(s)->print("%s: %s\r\n", name, val);
+  const int r = STREAM_IO(s)->send_header(name, val);
   if (r < 0) {
-    ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl;
+    ldout(s->cct, 0) << "ERROR: s->cio->send_header() returned err="
+                     << r << dendl;
   }
 }
 
-void dump_content_length(struct req_state *s, uint64_t len)
+void dump_header(struct req_state* const s,
+                 const boost::string_ref& name,
+                 ceph::buffer::list& bl)
+{
+  return dump_header(s, name, boost::string_ref(bl.c_str(), bl.length()));
+}
+
+void dump_header(struct req_state* const s,
+                 const boost::string_ref& name,
+                 const long long val)
+{
+  char buf[32];
+  const auto len = snprintf(buf, sizeof(buf), "%lld", val);
+
+  return dump_header(s, name, boost::string_ref(buf, len));
+}
+
+void dump_header(struct req_state* const s,
+                 const boost::string_ref& name,
+                 const utime_t& ut)
+{
+  char buf[32];
+  const auto len = snprintf(buf, sizeof(buf), "%lld.%05d",
+                           static_cast<long long>(ut.sec()),
+                            static_cast<int>(ut.usec() / 10));
+
+  return dump_header(s, name, boost::string_ref(buf, len));
+}
+
+void dump_content_length(struct req_state* const s, const uint64_t len)
 {
   int r = STREAM_IO(s)->send_content_length(len);
   if (r < 0) {
     ldout(s->cct, 0) << "ERROR: s->cio->send_content_length() returned err="
                      << r << dendl;
   }
-  r = STREAM_IO(s)->print("Accept-Ranges: bytes\r\n");
-  if (r < 0) {
-    ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl;
-  }
+  dump_header(s, "Accept-Ranges", "bytes");
 }
 
-void dump_etag(struct req_state * const s, const char * const etag)
+void dump_etag(struct req_state* const s, const boost::string_ref& etag)
 {
-  if ('\0' == *etag) {
+  if (etag.empty()) {
     return;
   }
 
-  int r;
   if (s->prot_flags & RGW_REST_SWIFT) {
-    r = STREAM_IO(s)->print("etag: %s\r\n", etag);
+    return dump_header(s, "etag", etag);
   } else {
-    r = STREAM_IO(s)->print("ETag: \"%s\"\r\n", etag);
-  }
-  if (r < 0) {
-    ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl;
+    /* We need two extra bytes for quotes. */
+    char buf[etag.size() + 2 + 1];
+    const auto len = snprintf(buf, sizeof(buf), "\"%s\"", etag.data());
+
+    return dump_header(s, "ETag", boost::string_ref(buf, len));
   }
 }
 
-void dump_pair(struct req_state *s, const char *key, const char *value)
+void dump_etag(struct req_state* const s, ceph::buffer::list& bl_etag)
+{
+  return dump_etag(s, boost::string_ref(bl_etag.c_str(), bl_etag.length()));
+}
+
+void dump_pair(struct req_state* const s,
+               const char* const key,
+               const char* const value)
 {
   if ( (strlen(key) > 0) && (strlen(value) > 0))
-    STREAM_IO(s)->print("%s: %s\r\n", key, value);
+    STREAM_IO(s)->send_header(key, value);
 }
 
 void dump_bucket_from_state(struct req_state *s)
@@ -425,7 +461,7 @@ void dump_bucket_from_state(struct req_state *s)
       } else {
         url_encode(s->bucket_name, b);
       }
-      STREAM_IO(s)->print("Bucket: %s\r\n", b.c_str());
+      STREAM_IO(s)->send_header("Bucket", b);
     }
   }
 }
@@ -447,12 +483,11 @@ void dump_uri_from_state(struct req_state *s)
       location += "/";
       if (!s->object.empty()) {
        location += s->object.name;
-       STREAM_IO(s)->print("Location: %s\r\n", location.c_str());
+       dump_header(s, "Location", location);
       }
     }
-  }
-  else {
-    STREAM_IO(s)->print("Location: \"%s\"\r\n", s->info.request_uri.c_str());
+  } else {
+    dump_header(s, "Location", "\"" + s->info.request_uri + "\"");
   }
 }
 
@@ -461,11 +496,11 @@ void dump_redirect(struct req_state *s, const string& redirect)
   if (redirect.empty())
     return;
 
-  STREAM_IO(s)->print("Location: %s\r\n", redirect.c_str());
+  STREAM_IO(s)->send_header("Location", redirect);
 }
 
-static bool dump_time_header_impl(char (&timestr)[TIME_BUF_SIZE],
-                                  const real_time t)
+static std::size_t dump_time_header_impl(char (&timestr)[TIME_BUF_SIZE],
+                                         const real_time t)
 {
   const utime_t ut(t);
   time_t secs = static_cast<time_t>(ut.sec());
@@ -473,29 +508,23 @@ static bool dump_time_header_impl(char (&timestr)[TIME_BUF_SIZE],
   struct tm result;
   const struct tm * const tmp = gmtime_r(&secs, &result);
   if (tmp == nullptr) {
-    return false;
-  }
-
-  if (strftime(timestr, sizeof(timestr),
-               "%a, %d %b %Y %H:%M:%S %Z", tmp) == 0) {
-    return false;
+    return 0;
   }
 
-  return true;
+  return strftime(timestr, sizeof(timestr),
+                  "%a, %d %b %Y %H:%M:%S %Z", tmp);
 }
 
 void dump_time_header(struct req_state *s, const char *name, real_time t)
 {
   char timestr[TIME_BUF_SIZE];
 
-  if (! dump_time_header_impl(timestr, t)) {
+  const std::size_t len = dump_time_header_impl(timestr, t);
+  if (len == 0) {
     return;
   }
 
-  int r = STREAM_IO(s)->print("%s: %s\r\n", name, timestr);
-  if (r < 0) {
-    ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl;
-  }
+  return dump_header(s, name, boost::string_ref(timestr, len));
 }
 
 std::string dump_time_to_str(const real_time& t)
@@ -515,14 +544,12 @@ void dump_last_modified(struct req_state *s, real_time t)
 void dump_epoch_header(struct req_state *s, const char *name, real_time t)
 {
   utime_t ut(t);
-  char sec_buf[32], nsec_buf[32];
-  snprintf(sec_buf, sizeof(sec_buf), "%lld", (long long)ut.sec());
-  snprintf(nsec_buf, sizeof(nsec_buf), "%09lld", (long long)ut.nsec());
+  char buf[65];
+  const auto len = snprintf(buf, sizeof(buf), "%lld.%09lld",
+                            (long long)ut.sec(),
+                            (long long)ut.nsec());
 
-  int r = STREAM_IO(s)->print("%s: %s.%s\r\n", name, sec_buf, nsec_buf);
-  if (r < 0) {
-    ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl;
-  }
+  return dump_header(s, name, boost::string_ref(buf, len));
 }
 
 void dump_time(struct req_state *s, const char *name, real_time *t)
@@ -549,24 +576,27 @@ void dump_access_control(struct req_state *s, const char *origin,
                         const char *hdr, const char *exp_hdr,
                         uint32_t max_age) {
   if (origin && (origin[0] != '\0')) {
-    STREAM_IO(s)->print("Access-Control-Allow-Origin: %s\r\n", origin);
+    dump_header(s, "Access-Control-Allow-Origin", origin);
     /* If the server specifies an origin host rather than "*",
      * then it must also include Origin in the Vary response header
      * to indicate to clients that server responses will differ
      * based on the value of the Origin request header.
      */
-    if (strcmp(origin, "*") != 0)
-      STREAM_IO(s)->print("Vary: Origin\r\n");
+    if (strcmp(origin, "*") != 0) {
+      dump_header(s, "Vary", "Origin");
+    }
 
-    if (meth && (meth[0] != '\0'))
-      STREAM_IO(s)->print("Access-Control-Allow-Methods: %s\r\n", meth);
-    if (hdr && (hdr[0] != '\0'))
-      STREAM_IO(s)->print("Access-Control-Allow-Headers: %s\r\n", hdr);
+    if (meth && (meth[0] != '\0')) {
+      dump_header(s, "Access-Control-Allow-Methods", meth);
+    }
+    if (hdr && (hdr[0] != '\0')) {
+      dump_header(s, "Access-Control-Allow-Headers", hdr);
+    }
     if (exp_hdr && (exp_hdr[0] != '\0')) {
-      STREAM_IO(s)->print("Access-Control-Expose-Headers: %s\r\n", exp_hdr);
+      dump_header(s, "Access-Control-Expose-Headers", exp_hdr);
     }
     if (max_age != CORS_MAX_AGE_INVALID) {
-      STREAM_IO(s)->print("Access-Control-Max-Age: %d\r\n", max_age);
+      dump_header(s, "Access-Control-Max-Age", max_age);
     }
   }
 }
@@ -597,10 +627,9 @@ void dump_start(struct req_state *s)
 void dump_trans_id(req_state *s)
 {
   if (s->prot_flags & RGW_REST_SWIFT) {
-    STREAM_IO(s)->print("X-Trans-Id: %s\r\n", s->trans_id.c_str());
-  }
-  else if (s->trans_id.length()) {
-    STREAM_IO(s)->print("x-amz-request-id: %s\r\n", s->trans_id.c_str());
+    dump_header(s, "X-Trans-Id", s->trans_id);
+  } else if (s->trans_id.length()) {
+    dump_header(s, "x-amz-request-id", s->trans_id);
   }
 }
 
@@ -615,7 +644,7 @@ void end_header(struct req_state* s, RGWOp* op, const char *content_type,
   if ((!s->err.is_err()) &&
       (s->bucket_info.owner != s->user->user_id) &&
       (s->bucket_info.requester_pays)) {
-    STREAM_IO(s)->print("x-amz-request-charged: requester\r\n");
+    dump_header(s, "x-amz-request-charged", "requester");
   }
 
   if (op) {
@@ -673,15 +702,10 @@ void end_header(struct req_state* s, RGWOp* op, const char *content_type,
     }
   }
 
-  int r;
   if (content_type) {
-      r = STREAM_IO(s)->print("Content-Type: %s\r\n", content_type);
-      if (r < 0) {
-       ldout(s->cct, 0) << "ERROR: STREAM_IO(s)->print() returned err=" << r
-                        << dendl;
-      }
+    dump_header(s, "Content-Type", content_type);
   }
-  r = STREAM_IO(s)->complete_header();
+  int r = STREAM_IO(s)->complete_header();
   if (r < 0) {
     ldout(s->cct, 0) << "ERROR: STREAM_IO(s)->complete_header() returned err="
                     << r << dendl;
@@ -773,24 +797,27 @@ void dump_continue(struct req_state *s)
   STREAM_IO(s)->send_100_continue();
 }
 
-void dump_range(struct req_state *s, uint64_t ofs, uint64_t end,
-               uint64_t total)
+void dump_range(struct req_state* const s,
+                const uint64_t ofs,
+                const uint64_t end,
+               const uint64_t total)
 {
-  char range_buf[128];
-
   /* dumping range into temp buffer first, as libfcgi will fail to digest
    * %lld */
+  char range_buf[128];
+  std::size_t len;
 
-  if (!total) {
-    snprintf(range_buf, sizeof(range_buf), "*/%lld", (long long)total);
+  if (! total) {
+    len = snprintf(range_buf, sizeof(range_buf), "bytes */%lld",
+                   static_cast<long long>(total));
   } else {
-    snprintf(range_buf, sizeof(range_buf), "%lld-%lld/%lld", (long long)ofs,
-               (long long)end, (long long)total);
-  }
-  int r = STREAM_IO(s)->print("Content-Range: bytes %s\r\n", range_buf);
-  if (r < 0) {
-    ldout(s->cct, 0) << "ERROR: s->cio->print() returned err=" << r << dendl;
+    len = snprintf(range_buf, sizeof(range_buf), "bytes %lld-%lld/%lld",
+                   static_cast<long long>(ofs),
+                   static_cast<long long>(end),
+                   static_cast<long long>(total));
   }
+
+  return dump_header(s, "Content-Range", boost::string_ref(range_buf, len));
 }
 
 int RGWGetObj_ObjStore::get_params()
index 977b481eb9ffc924e4a56b00adc2d218277dec1a..18ed1beffd8be274ccaece400a81616dd9da0c22 100644 (file)
@@ -6,6 +6,8 @@
 
 #define TIME_BUF_SIZE 128
 
+#include <boost/utility/string_ref.hpp>
+
 #include "common/ceph_json.h"
 #include "include/assert.h" /* needed because of common/ceph_json.h */
 #include "rgw_op.h"
@@ -529,10 +531,33 @@ extern void dump_start(struct req_state *s);
 extern void list_all_buckets_start(struct req_state *s);
 extern void dump_owner(struct req_state *s, rgw_user& id, string& name,
                       const char *section = NULL);
-extern void dump_string_header(struct req_state *s, const char *name,
-                              const char *val);
+extern void dump_header(struct req_state* s,
+                        const boost::string_ref& name,
+                        const boost::string_ref& val);
+extern void dump_header(struct req_state* s,
+                        const boost::string_ref& name,
+                        ceph::buffer::list& bl);
+extern void dump_header(struct req_state* s,
+                        const boost::string_ref& name,
+                        long long val);
+extern void dump_header(struct req_state* s,
+                        const boost::string_ref& name,
+                        const utime_t& val);
+template <class... Args>
+static inline void dump_header_prefixed(struct req_state* s,
+                                        const boost::string_ref& name_prefix,
+                                        const boost::string_ref& name,
+                                        Args&&... args) {
+  char full_name_buf[name_prefix.size() + name.size() + 1];
+  const auto len = snprintf(full_name_buf, sizeof(full_name_buf), "%.*s%.*s",
+                            name_prefix.length(), name_prefix.data(),
+                            name.length(), name.data());
+  boost::string_ref full_name(full_name_buf, len);
+  return dump_header(s, std::move(full_name), std::forward<Args>(args)...);
+}
 extern void dump_content_length(struct req_state *s, uint64_t len);
-extern void dump_etag(struct req_state *s, const char *etag);
+extern void dump_etag(struct req_state *s, const boost::string_ref& etag);
+extern void dump_etag(struct req_state *s, ceph::buffer::list& bl_etag);
 extern void dump_epoch_header(struct req_state *s, const char *name, real_time t);
 extern void dump_time_header(struct req_state *s, const char *name, real_time t);
 extern void dump_last_modified(struct req_state *s, real_time t);
index 35796d900805ef26c7cae124632dc5ae30e5e377..e904705fa69ef11beb20349a7a1e9977dbe21d54 100644 (file)
@@ -169,7 +169,7 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs,
   if (s->system_request &&
       s->info.args.exists(RGW_SYS_PARAM_PREFIX "prepend-metadata")) {
 
-    STREAM_IO(s)->print("Rgwx-Object-Size: %lld\r\n", (long long)total_len);
+    dump_header(s, "Rgwx-Object-Size", (long long)total_len);
 
     if (rgwx_stat) {
       /*
@@ -189,8 +189,7 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs,
     stringstream ss;
     jf.flush(ss);
     metadata_bl.append(ss.str());
-    STREAM_IO(s)->print("Rgwx-Embedded-Metadata-Len: %lld\r\n",
-                       (long long)metadata_bl.length());
+    dump_header(s, "Rgwx-Embedded-Metadata-Len", metadata_bl.length());
     total_len += metadata_bl.length();
   }
 
@@ -202,7 +201,7 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs,
     if (r < 0) {
       ldout(s->cct, 0) << "ERROR: failed to decode pg ver attr, ignoring" << dendl;
     }
-    STREAM_IO(s)->print("Rgwx-Obj-PG-Ver: %lld\r\n", (long long)pg_ver);
+    dump_header(s, "Rgwx-Obj-PG-Ver", pg_ver);
 
     uint32_t source_zone_short_id = 0;
     r = decode_attr_bl_single_value(attrs, RGW_ATTR_SOURCE_ZONE, &source_zone_short_id, (uint32_t)0);
@@ -210,7 +209,7 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs,
       ldout(s->cct, 0) << "ERROR: failed to decode pg ver attr, ignoring" << dendl;
     }
     if (source_zone_short_id != 0) {
-      STREAM_IO(s)->print("Rgwx-Source-Zone-Short-Id: %lld\r\n", (long long)source_zone_short_id);
+      dump_header(s, "Rgwx-Source-Zone-Short-Id", source_zone_short_id);
     }
   }
 
@@ -223,15 +222,11 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs,
        * legit to perform GET on them through S3 API. In such situation,
        * a client should receive the composited content with corresponding
        * etag value. */
-      dump_etag(s, lo_etag.c_str());
+      dump_etag(s, lo_etag);
     } else {
       auto iter = attrs.find(RGW_ATTR_ETAG);
       if (iter != attrs.end()) {
-        bufferlist& bl = iter->second;
-        if (bl.length()) {
-         const char * etag = bl.c_str();
-         dump_etag(s, etag);
-        }
+        dump_etag(s, iter->second);
       }
     }
 
@@ -265,7 +260,7 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs,
                         sizeof(RGW_ATTR_META_PREFIX)-1) == 0) {
         /* User custom metadata. */
         name += sizeof(RGW_ATTR_PREFIX) - 1;
-        STREAM_IO(s)->print("%s: %s\r\n", name, iter->second.c_str());
+        dump_header(s, name, iter->second);
       }
     }
   }
@@ -273,8 +268,7 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs,
 done:
   for (riter = response_attrs.begin(); riter != response_attrs.end();
        ++riter) {
-    STREAM_IO(s)->print("%s: %s\r\n", riter->first.c_str(),
-                       riter->second.c_str());
+    dump_header(s, riter->first, riter->second);
   }
 
   if (op_ret == -ERR_NOT_MODIFIED) {
@@ -868,11 +862,8 @@ void RGWGetBucketWebsite_ObjStore_S3::send_response()
 
 static void dump_bucket_metadata(struct req_state *s, RGWBucketEnt& bucket)
 {
-  char buf[32];
-  snprintf(buf, sizeof(buf), "%lld", (long long)bucket.count);
-  STREAM_IO(s)->print("X-RGW-Object-Count: %s\r\n", buf);
-  snprintf(buf, sizeof(buf), "%lld", (long long)bucket.size);
-  STREAM_IO(s)->print("X-RGW-Bytes-Used: %s\r\n", buf);
+  dump_header(s, "X-RGW-Object-Count", static_cast<long long>(bucket.count));
+  dump_header(s, "X-RGW-Bytes-Used", static_cast<long long>(bucket.size));
 }
 
 void RGWStatBucket_ObjStore_S3::send_response()
@@ -1334,7 +1325,7 @@ void RGWPutObj_ObjStore_S3::send_response()
     }
     if (!copy_source) {
       dump_errno(s);
-      dump_etag(s, etag.c_str());
+      dump_etag(s, etag);
       dump_content_length(s, 0);
     } else {
       dump_errno(s);
@@ -2175,10 +2166,10 @@ void RGWDeleteObj_ObjStore_S3::send_response()
   set_req_state_err(s, r);
   dump_errno(s);
   if (!version_id.empty()) {
-    dump_string_header(s, "x-amz-version-id", version_id.c_str());
+    dump_header(s, "x-amz-version-id", version_id);
   }
   if (delete_marker) {
-    dump_string_header(s, "x-amz-delete-marker", "true");
+    dump_header(s, "x-amz-delete-marker", "true");
   }
   end_header(s, this);
 }
index 631468c7f0af45857c8551c334a17dd95aa1dc68..8460e331fa44e4a5427e6b37d4758063e349af69 100644 (file)
@@ -78,47 +78,37 @@ static void dump_account_metadata(struct req_state * const s,
                                   const RGWQuotaInfo& quota,
                                   const RGWAccessControlPolicy_SWIFTAcct &policy)
 {
-  char buf[32];
-  utime_t now = ceph_clock_now(g_ceph_context);
-  snprintf(buf, sizeof(buf), "%0.5f", (double)now);
   /* Adding X-Timestamp to keep align with Swift API */
-  STREAM_IO(s)->print("X-Timestamp: %s\r\n", buf);
-  snprintf(buf, sizeof(buf), "%lld", (long long)buckets_count);
-  STREAM_IO(s)->print("X-Account-Container-Count: %s\r\n", buf);
-  snprintf(buf, sizeof(buf), "%lld", (long long)buckets_object_count);
-  STREAM_IO(s)->print("X-Account-Object-Count: %s\r\n", buf);
-  snprintf(buf, sizeof(buf), "%lld", (long long)buckets_size);
-  STREAM_IO(s)->print("X-Account-Bytes-Used: %s\r\n", buf);
-  snprintf(buf, sizeof(buf), "%lld", (long long)buckets_size_rounded);
-  STREAM_IO(s)->print("X-Account-Bytes-Used-Actual: %s\r\n", buf);
+  dump_header(s, "X-Timestamp", ceph_clock_now(g_ceph_context));
+
+  dump_header(s, "X-Account-Container-Count", buckets_count);
+  dump_header(s, "X-Account-Object-Count", buckets_object_count);
+  dump_header(s, "X-Account-Bytes-Used", buckets_size);
+  dump_header(s, "X-Account-Bytes-Used-Actual", buckets_size_rounded);
 
   /* Dump TempURL-related stuff */
   if (s->perm_mask == RGW_PERM_FULL_CONTROL) {
     auto iter = s->user->temp_url_keys.find(0);
-    if (iter != std::end(s->user->temp_url_keys) && !iter->second.empty()) {
-      STREAM_IO(s)->print("X-Account-Meta-Temp-Url-Key: %s\r\n",
-                         iter->second.c_str());
+    if (iter != std::end(s->user->temp_url_keys) && ! iter->second.empty()) {
+      dump_header(s, "X-Account-Meta-Temp-Url-Key", iter->second);
     }
 
     iter = s->user->temp_url_keys.find(1);
-    if (iter != std::end(s->user->temp_url_keys) && !iter->second.empty()) {
-      STREAM_IO(s)->print("X-Account-Meta-Temp-Url-Key-2: %s\r\n",
-                         iter->second.c_str());
+    if (iter != std::end(s->user->temp_url_keys) && ! iter->second.empty()) {
+      dump_header(s, "X-Account-Meta-Temp-Url-Key-2", iter->second);
     }
   }
 
   /* Dump quota headers. */
   if (quota.enabled) {
     if (quota.max_size >= 0) {
-      STREAM_IO(s)->print("X-Account-Meta-Quota-Bytes: %lld\r\n",
-                         (long long)quota.max_size);
+      dump_header(s, "X-Account-Meta-Quota-Bytes", quota.max_size);
     }
 
     /* Limit on the number of objects in a given account is a RadosGW's
      * extension. Swift's account quota WSGI filter doesn't support it. */
     if (quota.max_objects >= 0) {
-      STREAM_IO(s)->print("X-Account-Meta-Quota-Count: %lld\r\n",
-                         (long long)quota.max_objects);
+      dump_header(s, "X-Account-Meta-Quota-Count", quota.max_objects);
     }
   }
 
@@ -130,12 +120,11 @@ static void dump_account_metadata(struct req_state * const s,
     map<string, string>::const_iterator geniter = rgw_to_http_attrs.find(name);
 
     if (geniter != rgw_to_http_attrs.end()) {
-      STREAM_IO(s)->print("%s: %s\r\n", geniter->second.c_str(),
-                         iter->second.c_str());
+      dump_header(s, geniter->second, iter->second);
     } else if (strncmp(name, RGW_ATTR_META_PREFIX, PREFIX_LEN) == 0) {
-      STREAM_IO(s)->print("X-Account-Meta-%s: %s\r\n",
-                          camelcase_dash_http_attr(name + PREFIX_LEN).c_str(),
-                          iter->second.c_str());
+      dump_header_prefixed(s, "X-Account-Meta-",
+                           camelcase_dash_http_attr(name + PREFIX_LEN),
+                           iter->second);
     }
   }
 
@@ -143,7 +132,7 @@ static void dump_account_metadata(struct req_state * const s,
   string acct_acl;
   policy.to_str(acct_acl);
   if (acct_acl.size()) {
-    STREAM_IO(s)->print("X-Account-Access-Control: %s\r\n", acct_acl.c_str());
+    dump_header(s, "X-Account-Access-Control", std::move(acct_acl));
   }
 }
 
@@ -374,33 +363,26 @@ static void dump_container_metadata(struct req_state *s,
                                     const RGWQuotaInfo& quota,
                                     const RGWBucketWebsiteConf& ws_conf)
 {
-  char buf[32];
   /* Adding X-Timestamp to keep align with Swift API */
-  utime_t ut(s->bucket_info.creation_time);
-  snprintf(buf, sizeof(buf), "%lld.%05d",
-          (long long)ut.sec(), (int)(ut.usec() / 10));
-  STREAM_IO(s)->print("X-Timestamp: %s\r\n", buf);
-  snprintf(buf, sizeof(buf), "%lld", (long long)bucket.count);
-  STREAM_IO(s)->print("X-Container-Object-Count: %s\r\n", buf);
-  snprintf(buf, sizeof(buf), "%lld", (long long)bucket.size);
-  STREAM_IO(s)->print("X-Container-Bytes-Used: %s\r\n", buf);
-  snprintf(buf, sizeof(buf), "%lld", (long long)bucket.size_rounded);
-  STREAM_IO(s)->print("X-Container-Bytes-Used-Actual: %s\r\n", buf);
+  dump_header(s, "X-Timestamp", utime_t(s->bucket_info.creation_time));
+
+  dump_header(s, "X-Container-Object-Count", bucket.count);
+  dump_header(s, "X-Container-Bytes-Used", bucket.size);
+  dump_header(s, "X-Container-Bytes-Used-Actual", bucket.size_rounded);
 
   if (s->object.empty()) {
-    RGWAccessControlPolicy_SWIFT *swift_policy
-      = static_cast<RGWAccessControlPolicy_SWIFT *>(s->bucket_acl);
-    string read_acl, write_acl;
+    auto swift_policy = static_cast<RGWAccessControlPolicy_SWIFT*>(s->bucket_acl);
+    std::string read_acl, write_acl;
     swift_policy->to_str(read_acl, write_acl);
+
     if (read_acl.size()) {
-      STREAM_IO(s)->print("X-Container-Read: %s\r\n", read_acl.c_str());
+      dump_header(s, "X-Container-Read", read_acl);
     }
     if (write_acl.size()) {
-      STREAM_IO(s)->print("X-Container-Write: %s\r\n", write_acl.c_str());
+      dump_header(s, "X-Container-Write", write_acl);
     }
     if (!s->bucket_info.placement_rule.empty()) {
-      STREAM_IO(s)->print("X-Storage-Policy: %s\r\n",
-                         s->bucket_info.placement_rule.c_str());
+      dump_header(s, "X-Storage-Policy", s->bucket_info.placement_rule);
     }
 
     /* Dump user-defined metadata items and generic attrs. */
@@ -413,59 +395,53 @@ static void dump_container_metadata(struct req_state *s,
       map<string, string>::const_iterator geniter = rgw_to_http_attrs.find(name);
 
       if (geniter != rgw_to_http_attrs.end()) {
-        STREAM_IO(s)->print("%s: %s\r\n", geniter->second.c_str(),
-                           iter->second.c_str());
+        dump_header(s, geniter->second, iter->second);
       } else if (strncmp(name, RGW_ATTR_META_PREFIX, PREFIX_LEN) == 0) {
-        STREAM_IO(s)->print("X-Container-Meta-%s: %s\r\n",
-                            camelcase_dash_http_attr(name + PREFIX_LEN).c_str(),
-                            iter->second.c_str());
+        dump_header_prefixed(s, "X-Container-Meta-",
+                             camelcase_dash_http_attr(name + PREFIX_LEN),
+                             iter->second);
       }
     }
   }
 
   /* Dump container versioning info. */
-  if (!s->bucket_info.swift_ver_location.empty()) {
-    string encoded_loc;
-    url_encode(s->bucket_info.swift_ver_location, encoded_loc);
-    STREAM_IO(s)->print("X-Versions-Location: %s\r\n", encoded_loc.c_str());
+  if (! s->bucket_info.swift_ver_location.empty()) {
+    dump_header(s, "X-Versions-Location",
+                url_encode(s->bucket_info.swift_ver_location));
   }
 
   /* Dump quota headers. */
   if (quota.enabled) {
     if (quota.max_size >= 0) {
-      STREAM_IO(s)->print("X-Container-Meta-Quota-Bytes: %lld\r\n",
-                         (long long)quota.max_size);
+      dump_header(s, "X-Container-Meta-Quota-Bytes", quota.max_size);
     }
 
     if (quota.max_objects >= 0) {
-      STREAM_IO(s)->print("X-Container-Meta-Quota-Count: %lld\r\n",
-                         (long long)quota.max_objects);
+      dump_header(s, "X-Container-Meta-Quota-Count", quota.max_objects);
     }
   }
 
   /* Dump Static Website headers. */
   if (! ws_conf.index_doc_suffix.empty()) {
-    STREAM_IO(s)->print("X-Container-Meta-Web-Index: %s\r\n",
-                       ws_conf.index_doc_suffix.c_str());
+    dump_header(s, "X-Container-Meta-Web-Index", ws_conf.index_doc_suffix);
   }
 
   if (! ws_conf.error_doc.empty()) {
-    STREAM_IO(s)->print("X-Container-Meta-Web-Error: %s\r\n",
-                       ws_conf.error_doc.c_str());
+    dump_header(s, "X-Container-Meta-Web-Error", ws_conf.error_doc);
   }
 
   if (! ws_conf.subdir_marker.empty()) {
-    STREAM_IO(s)->print("X-Container-Meta-Web-Directory-Type: %s\r\n",
-                        ws_conf.subdir_marker.c_str());
+    dump_header(s, "X-Container-Meta-Web-Directory-Type",
+                ws_conf.subdir_marker);
   }
 
   if (! ws_conf.listing_css_doc.empty()) {
-    STREAM_IO(s)->print("X-Container-Meta-Web-Listings-CSS: %s\r\n",
-                       ws_conf.listing_css_doc.c_str());
+    dump_header(s, "X-Container-Meta-Web-Listings-CSS",
+                ws_conf.listing_css_doc);
   }
 
   if (ws_conf.listing_enabled) {
-    STREAM_IO(s)->print("X-Container-Meta-Web-Listings: true\r\n");
+    dump_header(s, "X-Container-Meta-Web-Listings", "true");
   }
 }
 
@@ -830,9 +806,9 @@ void RGWPutObj_ObjStore_SWIFT::send_response()
      * In response for PUT request we have to expose the second one.
      * The first one may be obtained by GET with "multipart-manifest=get"
      * in query string on a given SLO. */
-    dump_etag(s, ("\"" + lo_etag + "\"").c_str());
+    dump_etag(s, ("\"" + lo_etag + "\""));
   } else {
-    dump_etag(s, etag.c_str());
+    dump_etag(s, etag);
   }
 
   dump_last_modified(s, mtime);
@@ -1107,9 +1083,8 @@ static void dump_object_metadata(struct req_state * const s,
     } else if (strncmp(name, RGW_ATTR_META_PREFIX,
                       sizeof(RGW_ATTR_META_PREFIX)-1) == 0) {
       name += sizeof(RGW_ATTR_META_PREFIX) - 1;
-      STREAM_IO(s)->print("X-Object-Meta-%s: %s\r\n",
-                          camelcase_dash_http_attr(name).c_str(),
-                          kv.second.c_str());
+      dump_header_prefixed(s, "X-Object-Meta-",
+                           camelcase_dash_http_attr(name), kv.second);
     }
   }
 
@@ -1128,7 +1103,7 @@ static void dump_object_metadata(struct req_state * const s,
   }
 
   for (const auto kv : response_attrs) {
-    STREAM_IO(s)->print("%s: %s\r\n", kv.first.c_str(), kv.second.c_str());
+    dump_header(s, kv.first, kv.second);
   }
 
   const auto iter = attrs.find(RGW_ATTR_DELETE_AT);
@@ -1136,7 +1111,7 @@ static void dump_object_metadata(struct req_state * const s,
     utime_t delete_at;
     try {
       ::decode(delete_at, iter->second);
-      STREAM_IO(s)->print("X-Delete-At: %lu\r\n", delete_at.sec());
+      dump_header(s, "X-Delete-At", delete_at.sec());
     } catch (buffer::error& err) {
       ldout(s->cct, 0) << "ERROR: cannot decode object's " RGW_ATTR_DELETE_AT
                           " attr, ignoring"
@@ -1206,17 +1181,13 @@ void RGWCopyObj_ObjStore_SWIFT::send_partial_response(off_t ofs)
 
 void RGWCopyObj_ObjStore_SWIFT::dump_copy_info()
 {
-  /* Dump X-Copied-From */
-  string objname, bucketname;
-  url_encode(src_object.name, objname);
-  url_encode(src_bucket.name, bucketname);
-  STREAM_IO(s)->print("X-Copied-From: %s/%s\r\n", bucketname.c_str(),
-                     objname.c_str());
+  /* Dump X-Copied-From. */
+  dump_header(s, "X-Copied-From", url_encode(src_bucket.name) +
+              "/" + url_encode(src_object.name));
 
-  /* Dump X-Copied-From-Account */
-  string account_name;
-  url_encode(s->user->user_id.id, account_name); // XXX tenant
-  STREAM_IO(s)->print("X-Copied-From-Account: %s\r\n", account_name.c_str());
+  /* Dump X-Copied-From-Account. */
+  /* XXX tenant */
+  dump_header(s, "X-Copied-From-Account", url_encode(s->user->user_id.id));
 
   /* Dump X-Copied-From-Last-Modified. */
   dump_time_header(s, "X-Copied-From-Last-Modified", src_mtime);
@@ -1230,7 +1201,7 @@ void RGWCopyObj_ObjStore_SWIFT::send_response()
       op_ret = STATUS_CREATED;
     set_req_state_err(s, op_ret);
     dump_errno(s);
-    dump_etag(s, etag.c_str());
+    dump_etag(s, etag);
     dump_last_modified(s, mtime);
     dump_copy_info();
     get_contype_from_attrs(attrs, content_type);
@@ -1300,25 +1271,19 @@ int RGWGetObj_ObjStore_SWIFT::send_response_data(bufferlist& bl,
 
   dump_content_length(s, total_len);
   dump_last_modified(s, lastmod);
-  {
-    utime_t ut(lastmod);
-    STREAM_IO(s)->print("X-Timestamp: %lld.%05d\r\n", (long long)ut.sec(), (int)(ut.usec() / 10));
-  }
+  dump_header(s, "X-Timestamp", utime_t(lastmod));
+
   if (is_slo) {
-    STREAM_IO(s)->print("X-Static-Large-Object: True\r\n");
+    dump_header(s, "X-Static-Large-Object", "True");
   }
 
   if (! op_ret) {
     if (!lo_etag.empty()) {
-      dump_etag(s, ("\"" + lo_etag + "\"").c_str());
+      dump_etag(s, ("\"" + lo_etag + "\""));
     } else {
       auto iter = attrs.find(RGW_ATTR_ETAG);
       if (iter != attrs.end()) {
-        bufferlist& bl = iter->second;
-        if (bl.length()) {
-          char *etag = bl.c_str();
-          dump_etag(s, etag);
-        }
+        dump_etag(s, iter->second);
       }
     }
 
index e626f86e6c1301e8b33054d54b9f98a403c362a8..1ddbc4f8a0f23e19e52a975d62c9807f32a66f3b 100644 (file)
@@ -584,18 +584,22 @@ void RGW_SWIFT_Auth_Get::execute()
     tenant_path.append(info.user_id.to_str());
   }
 
-  STREAM_IO(s)->print("X-Storage-Url: %s%s/v1%s\r\n", swift_url.c_str(),
-               swift_prefix.c_str(), tenant_path.c_str());
+  dump_header(s, "X-Storage-Url", swift_url + swift_prefix + "/v1" +
+              tenant_path);
 
   if ((ret = encode_token(s->cct, swift_key->id, swift_key->key, bl)) < 0)
     goto done;
 
   {
-    char buf[bl.length() * 2 + 1];
-    buf_to_hex((const unsigned char *)bl.c_str(), bl.length(), buf);
+    static constexpr std::size_t PREFIX_LEN = strlen("AUTH_rgwtk");
+    char token_val[PREFIX_LEN + bl.length() * 2 + 1];
 
-    STREAM_IO(s)->print("X-Storage-Token: AUTH_rgwtk%s\r\n", buf);
-    STREAM_IO(s)->print("X-Auth-Token: AUTH_rgwtk%s\r\n", buf);
+    snprintf(token_val, PREFIX_LEN + 1, "AUTH_rgwtk");
+    buf_to_hex((const unsigned char *)bl.c_str(), bl.length(),
+               token_val + PREFIX_LEN);
+
+    dump_header(s, "X-Storage-Token", token_val);
+    dump_header(s, "X-Auth-Token", token_val);
   }
 
   ret = STATUS_NO_CONTENT;