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