1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
6 #include "rgw_rest_client.h"
7 #include "common/ceph_json.h"
8 #include "common/RefCountedObj.h"
9 #include "include/common_fwd.h"
10 #include "rgw_sal_fwd.h"
17 inline int parse_decode_json(T
& t
, bufferlist
& bl
)
20 if (!p
.parse(bl
.c_str(), bl
.length())) {
25 decode_json_obj(t
, &p
);
26 } catch (JSONDecoder::err
& e
) {
32 struct rgw_http_param_pair
{
37 // append a null-terminated rgw_http_param_pair list into a list of string pairs
38 inline void append_param_list(param_vec_t
& params
, const rgw_http_param_pair
* pp
)
40 while (pp
&& pp
->key
) {
41 std::string k
= pp
->key
;
42 std::string v
= (pp
->val
? pp
->val
: "");
43 params
.emplace_back(make_pair(std::move(k
), std::move(v
)));
48 // copy a null-terminated rgw_http_param_pair list into a list of std::string pairs
49 inline param_vec_t
make_param_list(const rgw_http_param_pair
* pp
)
52 append_param_list(params
, pp
);
56 inline param_vec_t
make_param_list(const std::map
<std::string
, std::string
> *pp
)
62 for (auto iter
: *pp
) {
63 params
.emplace_back(make_pair(iter
.first
, iter
.second
));
71 std::vector
<std::string
> endpoints
;
73 std::string self_zone_group
;
74 std::string remote_id
;
75 std::optional
<std::string
> api_name
;
77 std::atomic
<int64_t> counter
= { 0 };
81 RGWRESTConn(CephContext
*_cct
,
82 rgw::sal::Driver
* driver
,
83 const std::string
& _remote_id
,
84 const std::list
<std::string
>& endpoints
,
85 std::optional
<std::string
> _api_name
,
86 HostStyle _host_style
= PathStyle
);
87 RGWRESTConn(CephContext
*_cct
,
88 const std::string
& _remote_id
,
89 const std::list
<std::string
>& endpoints
,
91 std::string _zone_group
,
92 std::optional
<std::string
> _api_name
,
93 HostStyle _host_style
= PathStyle
);
95 // custom move needed for atomic
96 RGWRESTConn(RGWRESTConn
&& other
);
97 RGWRESTConn
& operator=(RGWRESTConn
&& other
);
98 virtual ~RGWRESTConn() = default;
100 int get_url(std::string
& endpoint
);
101 std::string
get_url();
102 const std::string
& get_self_zonegroup() {
103 return self_zone_group
;
105 const std::string
& get_remote_id() {
108 RGWAccessKey
& get_key() {
112 std::optional
<std::string
> get_api_name() const {
116 HostStyle
get_host_style() {
120 CephContext
*get_ctx() {
123 size_t get_endpoint_count() const { return endpoints
.size(); }
125 virtual void populate_params(param_vec_t
& params
, const rgw_user
*uid
, const std::string
& zonegroup
);
128 int forward(const DoutPrefixProvider
*dpp
, const rgw_user
& uid
, req_info
& info
, obj_version
*objv
, size_t max_response
, bufferlist
*inbl
, bufferlist
*outbl
, optional_yield y
);
131 int forward_iam_request(const DoutPrefixProvider
*dpp
, const RGWAccessKey
& key
, req_info
& info
, obj_version
*objv
, size_t max_response
, bufferlist
*inbl
, bufferlist
*outbl
, optional_yield y
);
135 int put_obj_send_init(const rgw_obj
& obj
, const rgw_http_param_pair
*extra_params
, RGWRESTStreamS3PutObj
**req
);
136 int put_obj_async_init(const DoutPrefixProvider
*dpp
, const rgw_user
& uid
, const rgw_obj
& obj
,
137 std::map
<std::string
, bufferlist
>& attrs
, RGWRESTStreamS3PutObj
**req
);
138 int complete_request(RGWRESTStreamS3PutObj
*req
, std::string
& etag
,
139 ceph::real_time
*mtime
, optional_yield y
);
141 struct get_obj_params
{
143 req_info
*info
{nullptr};
144 const ceph::real_time
*mod_ptr
{nullptr};
145 const ceph::real_time
*unmod_ptr
{nullptr};
146 bool high_precision_time
{true};
150 uint32_t mod_zone_id
{0};
151 uint64_t mod_pg_ver
{0};
153 bool prepend_metadata
{false};
155 bool rgwx_stat
{false};
156 bool sync_manifest
{false};
157 bool sync_cloudtiered
{false};
159 bool skip_decrypt
{true};
160 RGWHTTPStreamRWRequest::ReceiveCB
*cb
{nullptr};
162 bool range_is_set
{false};
163 uint64_t range_start
{0};
164 uint64_t range_end
{0};
165 rgw_zone_set_entry
*dst_zone_trace
{nullptr};
168 int get_obj(const DoutPrefixProvider
*dpp
, const rgw_obj
& obj
, const get_obj_params
& params
, bool send
, RGWRESTStreamRWRequest
**req
);
170 int get_obj(const DoutPrefixProvider
*dpp
, const rgw_user
& uid
, req_info
*info
/* optional */, const rgw_obj
& obj
,
171 const ceph::real_time
*mod_ptr
, const ceph::real_time
*unmod_ptr
,
172 uint32_t mod_zone_id
, uint64_t mod_pg_ver
,
173 bool prepend_metadata
, bool get_op
, bool rgwx_stat
, bool sync_manifest
,
174 bool skip_decrypt
, rgw_zone_set_entry
*dst_zone_trace
, bool sync_cloudtiered
,
175 bool send
, RGWHTTPStreamRWRequest::ReceiveCB
*cb
, RGWRESTStreamRWRequest
**req
);
176 int complete_request(RGWRESTStreamRWRequest
*req
,
178 ceph::real_time
*mtime
,
180 std::map
<std::string
, std::string
> *pattrs
,
181 std::map
<std::string
, std::string
> *pheaders
,
184 int get_resource(const DoutPrefixProvider
*dpp
,
185 const std::string
& resource
,
186 param_vec_t
*extra_params
,
187 std::map
<std::string
, std::string
>* extra_headers
,
189 bufferlist
*send_data
,
193 int send_resource(const DoutPrefixProvider
*dpp
,
194 const std::string
& method
,
195 const std::string
& resource
,
196 rgw_http_param_pair
*extra_params
,
197 std::map
<std::string
, std::string
>* extra_headers
,
199 bufferlist
*send_data
,
204 int get_json_resource(const DoutPrefixProvider
*dpp
, const std::string
& resource
, param_vec_t
*params
,
205 bufferlist
*in_data
, optional_yield y
, T
& t
);
207 int get_json_resource(const DoutPrefixProvider
*dpp
, const std::string
& resource
, param_vec_t
*params
,
208 optional_yield y
, T
& t
);
210 int get_json_resource(const DoutPrefixProvider
*dpp
, const std::string
& resource
, const rgw_http_param_pair
*pp
,
211 optional_yield y
, T
& t
);
214 void populate_zonegroup(param_vec_t
& params
, const std::string
& zonegroup
) {
215 if (!zonegroup
.empty()) {
216 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"zonegroup", zonegroup
));
219 void populate_uid(param_vec_t
& params
, const rgw_user
*uid
) {
221 std::string uid_str
= uid
->to_str();
223 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"uid", uid_str
));
229 class S3RESTConn
: public RGWRESTConn
{
233 S3RESTConn(CephContext
*_cct
, rgw::sal::Driver
* driver
, const std::string
& _remote_id
, const std::list
<std::string
>& endpoints
, std::optional
<std::string
> _api_name
, HostStyle _host_style
= PathStyle
) :
234 RGWRESTConn(_cct
, driver
, _remote_id
, endpoints
, _api_name
, _host_style
) {}
235 S3RESTConn(CephContext
*_cct
, const std::string
& _remote_id
, const std::list
<std::string
>& endpoints
, RGWAccessKey _cred
, std::string _zone_group
, std::optional
<std::string
> _api_name
, HostStyle _host_style
= PathStyle
):
236 RGWRESTConn(_cct
, _remote_id
, endpoints
, _cred
, _zone_group
, _api_name
, _host_style
) {}
237 ~S3RESTConn() override
= default;
239 void populate_params(param_vec_t
& params
, const rgw_user
*uid
, const std::string
& zonegroup
) override
{
240 // do not populate any params in S3 REST Connection.
247 int RGWRESTConn::get_json_resource(const DoutPrefixProvider
*dpp
, const std::string
& resource
, param_vec_t
*params
,
248 bufferlist
*in_data
, optional_yield y
, T
& t
)
251 int ret
= get_resource(dpp
, resource
, params
, nullptr, bl
, in_data
, nullptr, y
);
256 ret
= parse_decode_json(t
, bl
);
265 int RGWRESTConn::get_json_resource(const DoutPrefixProvider
*dpp
, const std::string
& resource
, param_vec_t
*params
,
266 optional_yield y
, T
& t
)
268 return get_json_resource(dpp
, resource
, params
, nullptr, y
, t
);
272 int RGWRESTConn::get_json_resource(const DoutPrefixProvider
*dpp
, const std::string
& resource
, const rgw_http_param_pair
*pp
,
273 optional_yield y
, T
& t
)
275 param_vec_t params
= make_param_list(pp
);
276 return get_json_resource(dpp
, resource
, ¶ms
, y
, t
);
279 class RGWStreamIntoBufferlist
: public RGWHTTPStreamRWRequest::ReceiveCB
{
282 explicit RGWStreamIntoBufferlist(bufferlist
& _bl
) : bl(_bl
) {}
283 int handle_data(bufferlist
& inbl
, bool *pause
) override
{
284 bl
.claim_append(inbl
);
285 return inbl
.length();
289 class RGWRESTReadResource
: public RefCountedObject
, public RGWIOProvider
{
292 std::string resource
;
294 std::map
<std::string
, std::string
> headers
;
296 RGWStreamIntoBufferlist cb
;
299 RGWRESTStreamReadRequest req
;
301 void init_common(param_vec_t
*extra_headers
);
304 RGWRESTReadResource(RGWRESTConn
*_conn
,
305 const std::string
& _resource
,
306 const rgw_http_param_pair
*pp
,
307 param_vec_t
*extra_headers
,
308 RGWHTTPManager
*_mgr
);
310 RGWRESTReadResource(RGWRESTConn
*_conn
,
311 const std::string
& _resource
,
312 param_vec_t
& _params
,
313 param_vec_t
*extra_headers
,
314 RGWHTTPManager
*_mgr
);
315 ~RGWRESTReadResource() = default;
317 rgw_io_id
get_io_id(int io_type
) {
318 return req
.get_io_id(io_type
);
321 void set_io_user_info(void *user_info
) override
{
322 req
.set_io_user_info(user_info
);
325 void *get_io_user_info() override
{
326 return req
.get_io_user_info();
330 int decode_resource(T
*dest
);
332 int read(const DoutPrefixProvider
*dpp
, optional_yield y
);
334 int aio_read(const DoutPrefixProvider
*dpp
);
336 std::string
to_str() {
340 int get_http_status() {
341 return req
.get_http_status();
344 int wait(bufferlist
*pbl
, optional_yield y
) {
345 int ret
= req
.wait(y
);
350 if (req
.get_status() < 0) {
351 return req
.get_status();
358 int wait(T
*dest
, optional_yield y
);
361 int fetch(const DoutPrefixProvider
*dpp
, T
*dest
, optional_yield y
);
366 int RGWRESTReadResource::decode_resource(T
*dest
)
368 int ret
= req
.get_status();
372 ret
= parse_decode_json(*dest
, bl
);
380 int RGWRESTReadResource::fetch(const DoutPrefixProvider
*dpp
, T
*dest
, optional_yield y
)
382 int ret
= read(dpp
, y
);
387 ret
= decode_resource(dest
);
395 int RGWRESTReadResource::wait(T
*dest
, optional_yield y
)
397 int ret
= req
.wait(y
);
402 ret
= decode_resource(dest
);
409 class RGWRESTSendResource
: public RefCountedObject
, public RGWIOProvider
{
413 std::string resource
;
415 std::map
<std::string
, std::string
> headers
;
417 RGWStreamIntoBufferlist cb
;
420 RGWRESTStreamRWRequest req
;
422 void init_common(param_vec_t
*extra_headers
);
425 RGWRESTSendResource(RGWRESTConn
*_conn
,
426 const std::string
& _method
,
427 const std::string
& _resource
,
428 const rgw_http_param_pair
*pp
,
429 param_vec_t
*extra_headers
,
430 RGWHTTPManager
*_mgr
);
432 RGWRESTSendResource(RGWRESTConn
*_conn
,
433 const std::string
& _method
,
434 const std::string
& _resource
,
436 param_vec_t
*extra_headers
,
437 RGWHTTPManager
*_mgr
);
439 ~RGWRESTSendResource() = default;
441 rgw_io_id
get_io_id(int io_type
) {
442 return req
.get_io_id(io_type
);
445 void set_io_user_info(void *user_info
) override
{
446 req
.set_io_user_info(user_info
);
449 void *get_io_user_info() override
{
450 return req
.get_io_user_info();
453 int send(const DoutPrefixProvider
*dpp
, bufferlist
& bl
, optional_yield y
);
455 int aio_send(const DoutPrefixProvider
*dpp
, bufferlist
& bl
);
457 std::string
to_str() {
461 int get_http_status() {
462 return req
.get_http_status();
465 template <class E
= int>
466 int wait(bufferlist
*pbl
, optional_yield y
, E
*err_result
= nullptr) {
467 int ret
= req
.wait(y
);
470 if (ret
< 0 && err_result
) {
471 ret
= parse_decode_json(*err_result
, bl
);
474 return req
.get_status();
477 template <class T
, class E
= int>
478 int wait(T
*dest
, optional_yield y
, E
*err_result
= nullptr);
481 template <class T
, class E
>
482 int RGWRESTSendResource::wait(T
*dest
, optional_yield y
, E
*err_result
)
484 int ret
= req
.wait(y
);
486 ret
= req
.get_status();
489 if (ret
< 0 && err_result
) {
490 ret
= parse_decode_json(*err_result
, bl
);
497 ret
= parse_decode_json(*dest
, bl
);
505 class RGWRESTPostResource
: public RGWRESTSendResource
{
507 RGWRESTPostResource(RGWRESTConn
*_conn
,
508 const std::string
& _resource
,
509 const rgw_http_param_pair
*pp
,
510 param_vec_t
*extra_headers
,
511 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "POST", _resource
,
512 pp
, extra_headers
, _mgr
) {}
514 RGWRESTPostResource(RGWRESTConn
*_conn
,
515 const std::string
& _resource
,
517 param_vec_t
*extra_headers
,
518 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "POST", _resource
,
519 params
, extra_headers
, _mgr
) {}
523 class RGWRESTPutResource
: public RGWRESTSendResource
{
525 RGWRESTPutResource(RGWRESTConn
*_conn
,
526 const std::string
& _resource
,
527 const rgw_http_param_pair
*pp
,
528 param_vec_t
*extra_headers
,
529 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "PUT", _resource
,
530 pp
, extra_headers
, _mgr
) {}
532 RGWRESTPutResource(RGWRESTConn
*_conn
,
533 const std::string
& _resource
,
535 param_vec_t
*extra_headers
,
536 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "PUT", _resource
,
537 params
, extra_headers
, _mgr
) {}
541 class RGWRESTDeleteResource
: public RGWRESTSendResource
{
543 RGWRESTDeleteResource(RGWRESTConn
*_conn
,
544 const std::string
& _resource
,
545 const rgw_http_param_pair
*pp
,
546 param_vec_t
*extra_headers
,
547 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "DELETE", _resource
,
548 pp
, extra_headers
, _mgr
) {}
550 RGWRESTDeleteResource(RGWRESTConn
*_conn
,
551 const std::string
& _resource
,
553 param_vec_t
*extra_headers
,
554 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "DELETE", _resource
,
555 params
, extra_headers
, _mgr
) {}