]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: implement RGWHTTPHeadersCollector.
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Fri, 1 Apr 2016 15:40:19 +0000 (17:40 +0200)
committerRadoslaw Zarzynski <rzarzynski@mirantis.com>
Thu, 2 Jun 2016 13:12:10 +0000 (15:12 +0200)
Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
src/rgw/rgw_http_client.cc
src/rgw/rgw_http_client.h

index 4d7a1d2a010b7caf5a96f492b57a2b8c03d91d6f..d1708f3db8002c096c82c2561ff3e7c4950a0f00 100644 (file)
@@ -344,6 +344,39 @@ RGWHTTPClient::~RGWHTTPClient()
 }
 
 
+int RGWHTTPHeadersCollector::receive_header(void * const ptr, const size_t len)
+{
+  const std::string header_line(static_cast<const char * const>(ptr), len);
+
+  /* We're tokening the line that way due to backward compatibility. */
+  const size_t sep_loc = header_line.find_first_of(" \t:");
+
+  if (std::string::npos == sep_loc) {
+    /* Wrongly formatted header? Just skip it. */
+    return 0;
+  }
+
+  header_name_t name(header_line.substr(0, sep_loc));
+  if (0 == relevant_headers.count(name)) {
+    /* Not interested in this particular header. */
+    return 0;
+  }
+
+  /* Skip spaces and tabs after the separator. */
+  const size_t val_loc_s = header_line.find_first_not_of(' ', sep_loc + 1);
+  const size_t val_loc_e = header_line.find_first_of("\r\n", sep_loc + 1);
+
+  if (std::string::npos == val_loc_s || std::string::npos == val_loc_e) {
+    /* Empty value case. */
+    found_headers.emplace(name, header_value_t());
+  } else {
+    found_headers.emplace(name, header_value_t(
+        header_line.substr(val_loc_s, val_loc_e - val_loc_s)));
+  }
+
+  return 0;
+}
+
 #if HAVE_CURL_MULTI_WAIT
 
 static int do_curl_wait(CephContext *cct, CURLM *handle, int signal_fd)
index 3587f227efbfc2fcfebdf335ba945b27c8cb4446..3715a6930c5ea211806cdf5b24c4643372272a53 100644 (file)
@@ -102,6 +102,52 @@ public:
   int get_req_retcode();
 };
 
+
+class RGWHTTPHeadersCollector : public RGWHTTPClient {
+public:
+  /* Case insensitive comparator for containers carrying HTTP headers. */
+  struct CILess : public std::binary_function<std::string, std::string, bool> {
+    bool operator()(const std::string& lhs,
+                    const std::string& rhs) const {
+      return ::strcasecmp(lhs.c_str(), rhs.c_str()) < 0 ;
+    }
+  };
+
+  typedef std::string header_name_t;
+  typedef std::string header_value_t;
+  typedef std::set<header_name_t, CILess> header_spec_t;
+
+  RGWHTTPHeadersCollector(CephContext * const cct,
+                          const header_spec_t relevant_headers)
+    : RGWHTTPClient(cct),
+      relevant_headers(relevant_headers) {
+  }
+
+  int receive_header(void *ptr, size_t len) override;
+  int receive_data(void *ptr, size_t len) override {
+    return 0;
+  }
+
+  int send_data(void *ptr, size_t len) override {
+    return 0;
+  }
+
+  std::map<header_name_t, header_value_t, CILess> get_headers() const {
+    return found_headers;
+  }
+
+  /* Throws std::out_of_range */
+  const header_value_t& get_header_value(const header_name_t& name) const {
+    return found_headers.at(name);
+  }
+
+
+protected:
+  const std::set<header_name_t, CILess> relevant_headers;
+  std::map<header_name_t, header_value_t, CILess> found_headers;
+};
+
+
 class RGWCompletionManager;
 
 class RGWHTTPManager {