]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_rest_conn.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / rgw / rgw_rest_conn.h
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
7c673cae 3
9f95a23c 4#pragma once
7c673cae
FG
5
6#include "rgw_rados.h"
7#include "rgw_rest_client.h"
8#include "common/ceph_json.h"
9#include "common/RefCountedObj.h"
9f95a23c 10#include "include/common_fwd.h"
7c673cae
FG
11
12#include <atomic>
13
11fdf7f2 14class RGWSI_Zone;
7c673cae
FG
15
16template <class T>
81eedcae 17static int parse_decode_json(T& t, bufferlist& bl)
7c673cae
FG
18{
19 JSONParser p;
81eedcae
TL
20 if (!p.parse(bl.c_str(), bl.length())) {
21 return -EINVAL;
7c673cae
FG
22 }
23
24 try {
25 decode_json_obj(t, &p);
26 } catch (JSONDecoder::err& e) {
27 return -EINVAL;
28 }
29 return 0;
30}
31
32struct rgw_http_param_pair {
33 const char *key;
34 const char *val;
35};
36
11fdf7f2
TL
37// append a null-terminated rgw_http_param_pair list into a list of string pairs
38inline void append_param_list(param_vec_t& params, const rgw_http_param_pair* pp)
7c673cae 39{
7c673cae
FG
40 while (pp && pp->key) {
41 string k = pp->key;
42 string v = (pp->val ? pp->val : "");
43 params.emplace_back(make_pair(std::move(k), std::move(v)));
44 ++pp;
45 }
11fdf7f2
TL
46}
47
48// copy a null-terminated rgw_http_param_pair list into a list of string pairs
49inline param_vec_t make_param_list(const rgw_http_param_pair* pp)
50{
51 param_vec_t params;
52 append_param_list(params, pp);
7c673cae
FG
53 return params;
54}
55
a8e16298
TL
56inline param_vec_t make_param_list(const map<string, string> *pp)
57{
58 param_vec_t params;
59 if (!pp) {
60 return params;
61 }
62 for (auto iter : *pp) {
63 params.emplace_back(make_pair(iter.first, iter.second));
64 }
65 return params;
66}
67
7c673cae
FG
68class RGWRESTConn
69{
70 CephContext *cct;
71 vector<string> endpoints;
72 RGWAccessKey key;
73 string self_zone_group;
74 string remote_id;
11fdf7f2 75 HostStyle host_style;
7c673cae
FG
76 std::atomic<int64_t> counter = { 0 };
77
78public:
79
11fdf7f2
TL
80 RGWRESTConn(CephContext *_cct, RGWSI_Zone *zone_svc, const string& _remote_id, const list<string>& endpoints, HostStyle _host_style = PathStyle);
81 RGWRESTConn(CephContext *_cct, RGWSI_Zone *zone_svc, const string& _remote_id, const list<string>& endpoints, RGWAccessKey _cred, HostStyle _host_style = PathStyle);
82
7c673cae
FG
83 // custom move needed for atomic
84 RGWRESTConn(RGWRESTConn&& other);
85 RGWRESTConn& operator=(RGWRESTConn&& other);
11fdf7f2 86 virtual ~RGWRESTConn() = default;
7c673cae
FG
87
88 int get_url(string& endpoint);
89 string get_url();
90 const string& get_self_zonegroup() {
91 return self_zone_group;
92 }
93 const string& get_remote_id() {
94 return remote_id;
95 }
96 RGWAccessKey& get_key() {
97 return key;
98 }
99
11fdf7f2
TL
100 HostStyle get_host_style() {
101 return host_style;
102 }
103
7c673cae
FG
104 CephContext *get_ctx() {
105 return cct;
106 }
107 size_t get_endpoint_count() const { return endpoints.size(); }
108
11fdf7f2
TL
109 virtual void populate_params(param_vec_t& params, const rgw_user *uid, const string& zonegroup);
110
7c673cae
FG
111 /* sync request */
112 int forward(const rgw_user& uid, req_info& info, obj_version *objv, size_t max_response, bufferlist *inbl, bufferlist *outbl);
113
7c673cae 114
11fdf7f2
TL
115 /* async requests */
116 int put_obj_send_init(rgw_obj& obj, const rgw_http_param_pair *extra_params, RGWRESTStreamS3PutObj **req);
117 int put_obj_async(const rgw_user& uid, rgw_obj& obj, uint64_t obj_size,
118 map<string, bufferlist>& attrs, bool send, RGWRESTStreamS3PutObj **req);
119 int complete_request(RGWRESTStreamS3PutObj *req, string& etag, ceph::real_time *mtime);
120
121 struct get_obj_params {
122 rgw_user uid;
123 req_info *info{nullptr};
124 const ceph::real_time *mod_ptr{nullptr};
125 const ceph::real_time *unmod_ptr{nullptr};
126 bool high_precision_time{true};
127
128 string etag;
129
130 uint32_t mod_zone_id{0};
131 uint64_t mod_pg_ver{0};
132
133 bool prepend_metadata{false};
134 bool get_op{false};
135 bool rgwx_stat{false};
136 bool sync_manifest{false};
137
138 bool skip_decrypt{true};
139 RGWHTTPStreamRWRequest::ReceiveCB *cb{nullptr};
140
141 bool range_is_set{false};
142 uint64_t range_start{0};
143 uint64_t range_end{0};
144 };
145
146 int get_obj(const rgw_obj& obj, const get_obj_params& params, bool send, RGWRESTStreamRWRequest **req);
147
148 int get_obj(const rgw_user& uid, req_info *info /* optional */, const rgw_obj& obj,
7c673cae
FG
149 const ceph::real_time *mod_ptr, const ceph::real_time *unmod_ptr,
150 uint32_t mod_zone_id, uint64_t mod_pg_ver,
151 bool prepend_metadata, bool get_op, bool rgwx_stat, bool sync_manifest,
11fdf7f2
TL
152 bool skip_decrypt, bool send, RGWHTTPStreamRWRequest::ReceiveCB *cb, RGWRESTStreamRWRequest **req);
153 int complete_request(RGWRESTStreamRWRequest *req,
154 string *etag,
155 ceph::real_time *mtime,
156 uint64_t *psize,
157 map<string, string> *pattrs,
158 map<string, string> *pheaders);
7c673cae
FG
159
160 int get_resource(const string& resource,
161 param_vec_t *extra_params,
162 map<string, string>* extra_headers,
31f18b77
FG
163 bufferlist& bl,
164 bufferlist *send_data = nullptr,
165 RGWHTTPManager *mgr = nullptr);
7c673cae 166
31f18b77
FG
167 template <class T>
168 int get_json_resource(const string& resource, param_vec_t *params, bufferlist *in_data, T& t);
7c673cae
FG
169 template <class T>
170 int get_json_resource(const string& resource, param_vec_t *params, T& t);
171 template <class T>
172 int get_json_resource(const string& resource, const rgw_http_param_pair *pp, T& t);
11fdf7f2
TL
173
174private:
175 void populate_zonegroup(param_vec_t& params, const string& zonegroup) {
176 if (!zonegroup.empty()) {
177 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "zonegroup", zonegroup));
178 }
179 }
180 void populate_uid(param_vec_t& params, const rgw_user *uid) {
181 if (uid) {
182 string uid_str = uid->to_str();
183 if (!uid->empty()){
184 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "uid", uid_str));
185 }
186 }
187 }
188};
189
190class S3RESTConn : public RGWRESTConn {
191
192public:
193
194 S3RESTConn(CephContext *_cct, RGWSI_Zone *svc_zone, const string& _remote_id, const list<string>& endpoints, HostStyle _host_style = PathStyle) :
195 RGWRESTConn(_cct, svc_zone, _remote_id, endpoints, _host_style) {}
196
197 S3RESTConn(CephContext *_cct, RGWSI_Zone *svc_zone, const string& _remote_id, const list<string>& endpoints, RGWAccessKey _cred, HostStyle _host_style = PathStyle):
198 RGWRESTConn(_cct, svc_zone, _remote_id, endpoints, _cred, _host_style) {}
199 ~S3RESTConn() override = default;
200
201 void populate_params(param_vec_t& params, const rgw_user *uid, const string& zonegroup) override {
202 // do not populate any params in S3 REST Connection.
203 return;
204 }
7c673cae
FG
205};
206
207
208template<class T>
31f18b77 209int RGWRESTConn::get_json_resource(const string& resource, param_vec_t *params, bufferlist *in_data, T& t)
7c673cae
FG
210{
211 bufferlist bl;
31f18b77 212 int ret = get_resource(resource, params, nullptr, bl, in_data);
7c673cae
FG
213 if (ret < 0) {
214 return ret;
215 }
216
81eedcae 217 ret = parse_decode_json(t, bl);
7c673cae
FG
218 if (ret < 0) {
219 return ret;
220 }
221
222 return 0;
223}
224
31f18b77
FG
225template<class T>
226int RGWRESTConn::get_json_resource(const string& resource, param_vec_t *params, T& t)
227{
228 return get_json_resource(resource, params, nullptr, t);
229}
230
7c673cae
FG
231template<class T>
232int RGWRESTConn::get_json_resource(const string& resource, const rgw_http_param_pair *pp, T& t)
233{
234 param_vec_t params = make_param_list(pp);
235 return get_json_resource(resource, &params, t);
236}
237
11fdf7f2 238class RGWStreamIntoBufferlist : public RGWHTTPStreamRWRequest::ReceiveCB {
7c673cae
FG
239 bufferlist& bl;
240public:
11fdf7f2
TL
241 explicit RGWStreamIntoBufferlist(bufferlist& _bl) : bl(_bl) {}
242 int handle_data(bufferlist& inbl, bool *pause) override {
7c673cae 243 bl.claim_append(inbl);
11fdf7f2 244 return inbl.length();
7c673cae
FG
245 }
246};
247
11fdf7f2 248class RGWRESTReadResource : public RefCountedObject, public RGWIOProvider {
7c673cae
FG
249 CephContext *cct;
250 RGWRESTConn *conn;
251 string resource;
252 param_vec_t params;
253 map<string, string> headers;
254 bufferlist bl;
255 RGWStreamIntoBufferlist cb;
256
257 RGWHTTPManager *mgr;
258 RGWRESTStreamReadRequest req;
259
260 void init_common(param_vec_t *extra_headers);
261
262public:
263 RGWRESTReadResource(RGWRESTConn *_conn,
264 const string& _resource,
265 const rgw_http_param_pair *pp,
266 param_vec_t *extra_headers,
267 RGWHTTPManager *_mgr);
268
269 RGWRESTReadResource(RGWRESTConn *_conn,
270 const string& _resource,
271 param_vec_t& _params,
272 param_vec_t *extra_headers,
273 RGWHTTPManager *_mgr);
11fdf7f2 274 ~RGWRESTReadResource() = default;
7c673cae 275
11fdf7f2
TL
276 rgw_io_id get_io_id(int io_type) {
277 return req.get_io_id(io_type);
7c673cae 278 }
11fdf7f2
TL
279
280 void set_io_user_info(void *user_info) override {
281 req.set_io_user_info(user_info);
282 }
283
284 void *get_io_user_info() override {
285 return req.get_io_user_info();
7c673cae
FG
286 }
287
288 template <class T>
289 int decode_resource(T *dest);
290
291 int read();
292
293 int aio_read();
294
295 string to_str() {
296 return req.to_str();
297 }
298
299 int get_http_status() {
300 return req.get_http_status();
301 }
302
9f95a23c
TL
303 int wait(bufferlist *pbl, optional_yield y) {
304 int ret = req.wait(y);
7c673cae
FG
305 if (ret < 0) {
306 return ret;
307 }
308
309 if (req.get_status() < 0) {
310 return req.get_status();
311 }
312 *pbl = bl;
313 return 0;
314 }
315
316 template <class T>
9f95a23c 317 int wait(T *dest, optional_yield y);
7c673cae
FG
318
319 template <class T>
320 int fetch(T *dest);
321};
322
323
324template <class T>
325int RGWRESTReadResource::decode_resource(T *dest)
326{
327 int ret = req.get_status();
328 if (ret < 0) {
329 return ret;
330 }
81eedcae 331 ret = parse_decode_json(*dest, bl);
7c673cae
FG
332 if (ret < 0) {
333 return ret;
334 }
335 return 0;
336}
337
338template <class T>
339int RGWRESTReadResource::fetch(T *dest)
340{
341 int ret = read();
342 if (ret < 0) {
343 return ret;
344 }
345
346 ret = decode_resource(dest);
347 if (ret < 0) {
348 return ret;
349 }
350 return 0;
351}
352
353template <class T>
9f95a23c 354int RGWRESTReadResource::wait(T *dest, optional_yield y)
7c673cae 355{
9f95a23c 356 int ret = req.wait(y);
7c673cae
FG
357 if (ret < 0) {
358 return ret;
359 }
360
361 ret = decode_resource(dest);
362 if (ret < 0) {
363 return ret;
364 }
365 return 0;
366}
367
11fdf7f2 368class RGWRESTSendResource : public RefCountedObject, public RGWIOProvider {
7c673cae
FG
369 CephContext *cct;
370 RGWRESTConn *conn;
371 string method;
372 string resource;
373 param_vec_t params;
374 map<string, string> headers;
375 bufferlist bl;
376 RGWStreamIntoBufferlist cb;
377
378 RGWHTTPManager *mgr;
379 RGWRESTStreamRWRequest req;
380
381 void init_common(param_vec_t *extra_headers);
382
383public:
384 RGWRESTSendResource(RGWRESTConn *_conn,
385 const string& _method,
386 const string& _resource,
387 const rgw_http_param_pair *pp,
388 param_vec_t *extra_headers,
389 RGWHTTPManager *_mgr);
390
391 RGWRESTSendResource(RGWRESTConn *_conn,
392 const string& _method,
393 const string& _resource,
394 param_vec_t& params,
395 param_vec_t *extra_headers,
396 RGWHTTPManager *_mgr);
397
11fdf7f2
TL
398 ~RGWRESTSendResource() = default;
399
400 rgw_io_id get_io_id(int io_type) {
401 return req.get_io_id(io_type);
7c673cae 402 }
11fdf7f2
TL
403
404 void set_io_user_info(void *user_info) override {
405 req.set_io_user_info(user_info);
406 }
407
408 void *get_io_user_info() override {
409 return req.get_io_user_info();
7c673cae
FG
410 }
411
7c673cae
FG
412 int send(bufferlist& bl);
413
414 int aio_send(bufferlist& bl);
415
416 string to_str() {
417 return req.to_str();
418 }
419
420 int get_http_status() {
421 return req.get_http_status();
422 }
423
81eedcae 424 template <class E = int>
9f95a23c
TL
425 int wait(bufferlist *pbl, optional_yield y, E *err_result = nullptr) {
426 int ret = req.wait(y);
11fdf7f2 427 *pbl = bl;
7c673cae 428
81eedcae
TL
429 if (ret < 0 && err_result ) {
430 ret = parse_decode_json(*err_result, bl);
7c673cae 431 }
81eedcae
TL
432
433 return req.get_status();
7c673cae
FG
434 }
435
11fdf7f2 436 template <class T, class E = int>
9f95a23c 437 int wait(T *dest, optional_yield y, E *err_result = nullptr);
7c673cae
FG
438};
439
92f5a8d4 440template <class T, class E>
9f95a23c 441int RGWRESTSendResource::wait(T *dest, optional_yield y, E *err_result)
7c673cae 442{
9f95a23c 443 int ret = req.wait(y);
81eedcae
TL
444 if (ret >= 0) {
445 ret = req.get_status();
7c673cae 446 }
a8e16298 447
81eedcae
TL
448 if (ret < 0 && err_result) {
449 ret = parse_decode_json(*err_result, bl);
a8e16298
TL
450 }
451
7c673cae
FG
452 if (ret < 0) {
453 return ret;
454 }
7c673cae 455
81eedcae 456 ret = parse_decode_json(*dest, bl);
7c673cae
FG
457 if (ret < 0) {
458 return ret;
459 }
460 return 0;
81eedcae 461
7c673cae
FG
462}
463
464class RGWRESTPostResource : public RGWRESTSendResource {
465public:
466 RGWRESTPostResource(RGWRESTConn *_conn,
467 const string& _resource,
468 const rgw_http_param_pair *pp,
469 param_vec_t *extra_headers,
470 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "POST", _resource,
471 pp, extra_headers, _mgr) {}
472
473 RGWRESTPostResource(RGWRESTConn *_conn,
474 const string& _resource,
475 param_vec_t& params,
476 param_vec_t *extra_headers,
477 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "POST", _resource,
478 params, extra_headers, _mgr) {}
479
480};
481
482class RGWRESTPutResource : public RGWRESTSendResource {
483public:
484 RGWRESTPutResource(RGWRESTConn *_conn,
485 const string& _resource,
486 const rgw_http_param_pair *pp,
487 param_vec_t *extra_headers,
488 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "PUT", _resource,
489 pp, extra_headers, _mgr) {}
490
491 RGWRESTPutResource(RGWRESTConn *_conn,
492 const string& _resource,
493 param_vec_t& params,
494 param_vec_t *extra_headers,
495 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "PUT", _resource,
496 params, extra_headers, _mgr) {}
497
498};
499
500class RGWRESTDeleteResource : public RGWRESTSendResource {
501public:
502 RGWRESTDeleteResource(RGWRESTConn *_conn,
503 const string& _resource,
504 const rgw_http_param_pair *pp,
505 param_vec_t *extra_headers,
506 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "DELETE", _resource,
507 pp, extra_headers, _mgr) {}
508
509 RGWRESTDeleteResource(RGWRESTConn *_conn,
510 const string& _resource,
511 param_vec_t& params,
512 param_vec_t *extra_headers,
513 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "DELETE", _resource,
514 params, extra_headers, _mgr) {}
515
516};