1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_RGW_HTTP_CLIENT_H
5 #define CEPH_RGW_HTTP_CLIENT_H
7 #include "common/RWLock.h"
8 #include "common/Cond.h"
9 #include "rgw_common.h"
10 #include "rgw_string.h"
14 using param_pair_t = pair<string, string>;
15 using param_vec_t = vector<param_pair_t>;
17 struct rgw_http_req_data;
21 friend class RGWHTTPManager;
24 bufferlist::iterator send_iter;
29 rgw_http_req_data *req_data;
35 bool verify_ssl; // Do not validate self signed certificates, default to false
37 std::atomic<unsigned> stopped { 0 };
43 int init_request(const char *method,
45 rgw_http_req_data *req_data,
46 bool send_data_hint = false);
48 virtual int receive_header(void *ptr, size_t len) {
51 virtual int receive_data(void *ptr, size_t len) {
54 virtual int send_data(void *ptr, size_t len) {
58 /* Callbacks for libcurl. */
59 static size_t simple_receive_http_header(void *ptr,
63 static size_t receive_http_header(void *ptr,
68 static size_t simple_receive_http_data(void *ptr,
72 static size_t receive_http_data(void *ptr,
77 static size_t simple_send_http_data(void *ptr,
81 static size_t send_http_data(void *ptr,
86 static const long HTTP_STATUS_NOSTATUS = 0;
87 static const long HTTP_STATUS_UNAUTHORIZED = 401;
88 static const long HTTP_STATUS_NOTFOUND = 404;
90 virtual ~RGWHTTPClient();
91 explicit RGWHTTPClient(CephContext *cct)
94 http_status(HTTP_STATUS_NOSTATUS),
97 verify_ssl(cct->_conf->rgw_verify_ssl),
101 void set_user_info(void *info) {
105 void *get_user_info() {
109 void append_header(const string& name, const string& val) {
110 headers.push_back(pair<string, string>(name, val));
113 void set_send_length(size_t len) {
119 long get_http_status() const {
123 void set_verify_ssl(bool flag) {
127 int process(const char *method, const char *url);
128 int process(const char *url) { return process("GET", url); }
131 rgw_http_req_data *get_req_data() { return req_data; }
135 int get_req_retcode();
139 class RGWHTTPHeadersCollector : public RGWHTTPClient {
141 typedef std::string header_name_t;
142 typedef std::string header_value_t;
143 typedef std::set<header_name_t, ltstr_nocase> header_spec_t;
145 RGWHTTPHeadersCollector(CephContext * const cct,
146 const header_spec_t relevant_headers)
147 : RGWHTTPClient(cct),
148 relevant_headers(relevant_headers) {
151 std::map<header_name_t, header_value_t, ltstr_nocase> get_headers() const {
152 return found_headers;
155 /* Throws std::out_of_range */
156 const header_value_t& get_header_value(const header_name_t& name) const {
157 return found_headers.at(name);
161 int receive_header(void *ptr, size_t len) override;
163 int receive_data(void *ptr, size_t len) override {
167 int send_data(void *ptr, size_t len) override {
172 const std::set<header_name_t, ltstr_nocase> relevant_headers;
173 std::map<header_name_t, header_value_t, ltstr_nocase> found_headers;
177 class RGWHTTPTransceiver : public RGWHTTPHeadersCollector {
178 bufferlist * const read_bl;
179 std::string post_data;
180 size_t post_data_index;
183 RGWHTTPTransceiver(CephContext * const cct,
184 bufferlist * const read_bl,
185 const header_spec_t intercept_headers = {})
186 : RGWHTTPHeadersCollector(cct, intercept_headers),
191 RGWHTTPTransceiver(CephContext * const cct,
192 bufferlist * const read_bl,
193 const bool verify_ssl,
194 const header_spec_t intercept_headers = {})
195 : RGWHTTPHeadersCollector(cct, intercept_headers),
198 set_verify_ssl(verify_ssl);
201 void set_post_data(const std::string& _post_data) {
202 this->post_data = _post_data;
206 int send_data(void* ptr, size_t len) override;
208 int receive_data(void *ptr, size_t len) override {
209 read_bl->append((char *)ptr, len);
214 typedef RGWHTTPTransceiver RGWPostHTTPData;
217 class RGWCompletionManager;
219 class RGWHTTPManager {
221 RGWCompletionManager *completion_mgr;
224 std::atomic<unsigned> going_down { 0 };
225 std::atomic<unsigned> is_stopped { 0 };
228 map<uint64_t, rgw_http_req_data *> reqs;
229 list<rgw_http_req_data *> unregistered_reqs;
230 map<uint64_t, rgw_http_req_data *> complete_reqs;
232 int64_t max_threaded_req;
235 void register_request(rgw_http_req_data *req_data);
236 void complete_request(rgw_http_req_data *req_data);
237 void _complete_request(rgw_http_req_data *req_data);
238 void unregister_request(rgw_http_req_data *req_data);
239 void _unlink_request(rgw_http_req_data *req_data);
240 void unlink_request(rgw_http_req_data *req_data);
241 void finish_request(rgw_http_req_data *req_data, int r);
242 void _finish_request(rgw_http_req_data *req_data, int r);
243 int link_request(rgw_http_req_data *req_data);
245 void manage_pending_requests();
247 class ReqsThread : public Thread {
248 RGWHTTPManager *manager;
251 ReqsThread(RGWHTTPManager *_m) : manager(_m) {}
252 void *entry() override;
255 ReqsThread *reqs_thread;
257 void *reqs_thread_entry();
262 RGWHTTPManager(CephContext *_cct, RGWCompletionManager *completion_mgr = NULL);
268 int add_request(RGWHTTPClient *client, const char *method, const char *url,
269 bool send_data_hint = false);
270 int remove_request(RGWHTTPClient *client);
272 /* only for non threaded case */
273 int process_requests(bool wait_for_data, bool *done);
275 int complete_requests();