From a49e9e685d210d592b0f8e0883def3d5d764f79b Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Fri, 1 Apr 2016 17:40:19 +0200 Subject: [PATCH] rgw: implement RGWHTTPHeadersCollector. Signed-off-by: Radoslaw Zarzynski --- src/rgw/rgw_http_client.cc | 33 +++++++++++++++++++++++++++ src/rgw/rgw_http_client.h | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/rgw/rgw_http_client.cc b/src/rgw/rgw_http_client.cc index 4d7a1d2a010b7..d1708f3db8002 100644 --- a/src/rgw/rgw_http_client.cc +++ b/src/rgw/rgw_http_client.cc @@ -344,6 +344,39 @@ RGWHTTPClient::~RGWHTTPClient() } +int RGWHTTPHeadersCollector::receive_header(void * const ptr, const size_t len) +{ + const std::string header_line(static_cast(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) diff --git a/src/rgw/rgw_http_client.h b/src/rgw/rgw_http_client.h index 3587f227efbfc..3715a6930c5ea 100644 --- a/src/rgw/rgw_http_client.h +++ b/src/rgw/rgw_http_client.h @@ -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 { + 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_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 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 relevant_headers; + std::map found_headers; +}; + + class RGWCompletionManager; class RGWHTTPManager { -- 2.39.5