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"
16 static int parse_decode_json(T
& t
, bufferlist
& bl
)
19 if (!p
.parse(bl
.c_str(), bl
.length())) {
24 decode_json_obj(t
, &p
);
25 } catch (JSONDecoder::err
& e
) {
31 struct rgw_http_param_pair
{
36 // append a null-terminated rgw_http_param_pair list into a list of string pairs
37 inline void append_param_list(param_vec_t
& params
, const rgw_http_param_pair
* pp
)
39 while (pp
&& pp
->key
) {
41 string v
= (pp
->val
? pp
->val
: "");
42 params
.emplace_back(make_pair(std::move(k
), std::move(v
)));
47 // copy a null-terminated rgw_http_param_pair list into a list of string pairs
48 inline param_vec_t
make_param_list(const rgw_http_param_pair
* pp
)
51 append_param_list(params
, pp
);
55 inline param_vec_t
make_param_list(const map
<string
, string
> *pp
)
61 for (auto iter
: *pp
) {
62 params
.emplace_back(make_pair(iter
.first
, iter
.second
));
70 vector
<string
> endpoints
;
72 string self_zone_group
;
75 std::atomic
<int64_t> counter
= { 0 };
79 RGWRESTConn(CephContext
*_cct
, RGWSI_Zone
*zone_svc
, const string
& _remote_id
, const list
<string
>& endpoints
, HostStyle _host_style
= PathStyle
);
80 RGWRESTConn(CephContext
*_cct
, RGWSI_Zone
*zone_svc
, const string
& _remote_id
, const list
<string
>& endpoints
, RGWAccessKey _cred
, HostStyle _host_style
= PathStyle
);
82 // custom move needed for atomic
83 RGWRESTConn(RGWRESTConn
&& other
);
84 RGWRESTConn
& operator=(RGWRESTConn
&& other
);
85 virtual ~RGWRESTConn() = default;
87 int get_url(string
& endpoint
);
89 const string
& get_self_zonegroup() {
90 return self_zone_group
;
92 const string
& get_remote_id() {
95 RGWAccessKey
& get_key() {
99 HostStyle
get_host_style() {
103 CephContext
*get_ctx() {
106 size_t get_endpoint_count() const { return endpoints
.size(); }
108 virtual void populate_params(param_vec_t
& params
, const rgw_user
*uid
, const string
& zonegroup
);
111 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
);
115 int put_obj_send_init(rgw::sal::RGWObject
* obj
, const rgw_http_param_pair
*extra_params
, RGWRESTStreamS3PutObj
**req
);
116 int put_obj_async(const DoutPrefixProvider
*dpp
, const rgw_user
& uid
, rgw::sal::RGWObject
* obj
, uint64_t obj_size
,
117 map
<string
, bufferlist
>& attrs
, bool send
, RGWRESTStreamS3PutObj
**req
);
118 int complete_request(RGWRESTStreamS3PutObj
*req
, string
& etag
,
119 ceph::real_time
*mtime
, optional_yield y
);
121 struct get_obj_params
{
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};
130 uint32_t mod_zone_id
{0};
131 uint64_t mod_pg_ver
{0};
133 bool prepend_metadata
{false};
135 bool rgwx_stat
{false};
136 bool sync_manifest
{false};
138 bool skip_decrypt
{true};
139 RGWHTTPStreamRWRequest::ReceiveCB
*cb
{nullptr};
141 bool range_is_set
{false};
142 uint64_t range_start
{0};
143 uint64_t range_end
{0};
146 int get_obj(const DoutPrefixProvider
*dpp
, const rgw::sal::RGWObject
* obj
, const get_obj_params
& params
, bool send
, RGWRESTStreamRWRequest
**req
);
148 int get_obj(const DoutPrefixProvider
*dpp
, const rgw_user
& uid
, req_info
*info
/* optional */, const rgw::sal::RGWObject
* obj
,
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
,
152 bool skip_decrypt
, bool send
, RGWHTTPStreamRWRequest::ReceiveCB
*cb
, RGWRESTStreamRWRequest
**req
);
153 int complete_request(RGWRESTStreamRWRequest
*req
,
155 ceph::real_time
*mtime
,
157 map
<string
, string
> *pattrs
,
158 map
<string
, string
> *pheaders
,
161 int get_resource(const DoutPrefixProvider
*dpp
,
162 const string
& resource
,
163 param_vec_t
*extra_params
,
164 map
<string
, string
>* extra_headers
,
166 bufferlist
*send_data
,
171 int get_json_resource(const DoutPrefixProvider
*dpp
, const string
& resource
, param_vec_t
*params
,
172 bufferlist
*in_data
, optional_yield y
, T
& t
);
174 int get_json_resource(const DoutPrefixProvider
*dpp
, const string
& resource
, param_vec_t
*params
,
175 optional_yield y
, T
& t
);
177 int get_json_resource(const DoutPrefixProvider
*dpp
, const string
& resource
, const rgw_http_param_pair
*pp
,
178 optional_yield y
, T
& t
);
181 void populate_zonegroup(param_vec_t
& params
, const string
& zonegroup
) {
182 if (!zonegroup
.empty()) {
183 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"zonegroup", zonegroup
));
186 void populate_uid(param_vec_t
& params
, const rgw_user
*uid
) {
188 string uid_str
= uid
->to_str();
190 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"uid", uid_str
));
196 class S3RESTConn
: public RGWRESTConn
{
200 S3RESTConn(CephContext
*_cct
, RGWSI_Zone
*svc_zone
, const string
& _remote_id
, const list
<string
>& endpoints
, HostStyle _host_style
= PathStyle
) :
201 RGWRESTConn(_cct
, svc_zone
, _remote_id
, endpoints
, _host_style
) {}
203 S3RESTConn(CephContext
*_cct
, RGWSI_Zone
*svc_zone
, const string
& _remote_id
, const list
<string
>& endpoints
, RGWAccessKey _cred
, HostStyle _host_style
= PathStyle
):
204 RGWRESTConn(_cct
, svc_zone
, _remote_id
, endpoints
, _cred
, _host_style
) {}
205 ~S3RESTConn() override
= default;
207 void populate_params(param_vec_t
& params
, const rgw_user
*uid
, const string
& zonegroup
) override
{
208 // do not populate any params in S3 REST Connection.
215 int RGWRESTConn::get_json_resource(const DoutPrefixProvider
*dpp
, const string
& resource
, param_vec_t
*params
,
216 bufferlist
*in_data
, optional_yield y
, T
& t
)
219 int ret
= get_resource(dpp
, resource
, params
, nullptr, bl
, in_data
, nullptr, y
);
224 ret
= parse_decode_json(t
, bl
);
233 int RGWRESTConn::get_json_resource(const DoutPrefixProvider
*dpp
, const string
& resource
, param_vec_t
*params
,
234 optional_yield y
, T
& t
)
236 return get_json_resource(dpp
, resource
, params
, nullptr, y
, t
);
240 int RGWRESTConn::get_json_resource(const DoutPrefixProvider
*dpp
, const string
& resource
, const rgw_http_param_pair
*pp
,
241 optional_yield y
, T
& t
)
243 param_vec_t params
= make_param_list(pp
);
244 return get_json_resource(dpp
, resource
, ¶ms
, y
, t
);
247 class RGWStreamIntoBufferlist
: public RGWHTTPStreamRWRequest::ReceiveCB
{
250 explicit RGWStreamIntoBufferlist(bufferlist
& _bl
) : bl(_bl
) {}
251 int handle_data(bufferlist
& inbl
, bool *pause
) override
{
252 bl
.claim_append(inbl
);
253 return inbl
.length();
257 class RGWRESTReadResource
: public RefCountedObject
, public RGWIOProvider
{
262 map
<string
, string
> headers
;
264 RGWStreamIntoBufferlist cb
;
267 RGWRESTStreamReadRequest req
;
269 void init_common(param_vec_t
*extra_headers
);
272 RGWRESTReadResource(RGWRESTConn
*_conn
,
273 const string
& _resource
,
274 const rgw_http_param_pair
*pp
,
275 param_vec_t
*extra_headers
,
276 RGWHTTPManager
*_mgr
);
278 RGWRESTReadResource(RGWRESTConn
*_conn
,
279 const string
& _resource
,
280 param_vec_t
& _params
,
281 param_vec_t
*extra_headers
,
282 RGWHTTPManager
*_mgr
);
283 ~RGWRESTReadResource() = default;
285 rgw_io_id
get_io_id(int io_type
) {
286 return req
.get_io_id(io_type
);
289 void set_io_user_info(void *user_info
) override
{
290 req
.set_io_user_info(user_info
);
293 void *get_io_user_info() override
{
294 return req
.get_io_user_info();
298 int decode_resource(T
*dest
);
300 int read(const DoutPrefixProvider
*dpp
, optional_yield y
);
302 int aio_read(const DoutPrefixProvider
*dpp
);
308 int get_http_status() {
309 return req
.get_http_status();
312 int wait(bufferlist
*pbl
, optional_yield y
) {
313 int ret
= req
.wait(y
);
318 if (req
.get_status() < 0) {
319 return req
.get_status();
326 int wait(T
*dest
, optional_yield y
);
329 int fetch(const DoutPrefixProvider
*dpp
, T
*dest
, optional_yield y
);
334 int RGWRESTReadResource::decode_resource(T
*dest
)
336 int ret
= req
.get_status();
340 ret
= parse_decode_json(*dest
, bl
);
348 int RGWRESTReadResource::fetch(const DoutPrefixProvider
*dpp
, T
*dest
, optional_yield y
)
350 int ret
= read(dpp
, y
);
355 ret
= decode_resource(dest
);
363 int RGWRESTReadResource::wait(T
*dest
, optional_yield y
)
365 int ret
= req
.wait(y
);
370 ret
= decode_resource(dest
);
377 class RGWRESTSendResource
: public RefCountedObject
, public RGWIOProvider
{
383 map
<string
, string
> headers
;
385 RGWStreamIntoBufferlist cb
;
388 RGWRESTStreamRWRequest req
;
390 void init_common(param_vec_t
*extra_headers
);
393 RGWRESTSendResource(RGWRESTConn
*_conn
,
394 const string
& _method
,
395 const string
& _resource
,
396 const rgw_http_param_pair
*pp
,
397 param_vec_t
*extra_headers
,
398 RGWHTTPManager
*_mgr
);
400 RGWRESTSendResource(RGWRESTConn
*_conn
,
401 const string
& _method
,
402 const string
& _resource
,
404 param_vec_t
*extra_headers
,
405 RGWHTTPManager
*_mgr
);
407 ~RGWRESTSendResource() = default;
409 rgw_io_id
get_io_id(int io_type
) {
410 return req
.get_io_id(io_type
);
413 void set_io_user_info(void *user_info
) override
{
414 req
.set_io_user_info(user_info
);
417 void *get_io_user_info() override
{
418 return req
.get_io_user_info();
421 int send(const DoutPrefixProvider
*dpp
, bufferlist
& bl
, optional_yield y
);
423 int aio_send(const DoutPrefixProvider
*dpp
, bufferlist
& bl
);
429 int get_http_status() {
430 return req
.get_http_status();
433 template <class E
= int>
434 int wait(bufferlist
*pbl
, optional_yield y
, E
*err_result
= nullptr) {
435 int ret
= req
.wait(y
);
438 if (ret
< 0 && err_result
) {
439 ret
= parse_decode_json(*err_result
, bl
);
442 return req
.get_status();
445 template <class T
, class E
= int>
446 int wait(T
*dest
, optional_yield y
, E
*err_result
= nullptr);
449 template <class T
, class E
>
450 int RGWRESTSendResource::wait(T
*dest
, optional_yield y
, E
*err_result
)
452 int ret
= req
.wait(y
);
454 ret
= req
.get_status();
457 if (ret
< 0 && err_result
) {
458 ret
= parse_decode_json(*err_result
, bl
);
465 ret
= parse_decode_json(*dest
, bl
);
473 class RGWRESTPostResource
: public RGWRESTSendResource
{
475 RGWRESTPostResource(RGWRESTConn
*_conn
,
476 const string
& _resource
,
477 const rgw_http_param_pair
*pp
,
478 param_vec_t
*extra_headers
,
479 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "POST", _resource
,
480 pp
, extra_headers
, _mgr
) {}
482 RGWRESTPostResource(RGWRESTConn
*_conn
,
483 const string
& _resource
,
485 param_vec_t
*extra_headers
,
486 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "POST", _resource
,
487 params
, extra_headers
, _mgr
) {}
491 class RGWRESTPutResource
: public RGWRESTSendResource
{
493 RGWRESTPutResource(RGWRESTConn
*_conn
,
494 const string
& _resource
,
495 const rgw_http_param_pair
*pp
,
496 param_vec_t
*extra_headers
,
497 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "PUT", _resource
,
498 pp
, extra_headers
, _mgr
) {}
500 RGWRESTPutResource(RGWRESTConn
*_conn
,
501 const string
& _resource
,
503 param_vec_t
*extra_headers
,
504 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "PUT", _resource
,
505 params
, extra_headers
, _mgr
) {}
509 class RGWRESTDeleteResource
: public RGWRESTSendResource
{
511 RGWRESTDeleteResource(RGWRESTConn
*_conn
,
512 const string
& _resource
,
513 const rgw_http_param_pair
*pp
,
514 param_vec_t
*extra_headers
,
515 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "DELETE", _resource
,
516 pp
, extra_headers
, _mgr
) {}
518 RGWRESTDeleteResource(RGWRESTConn
*_conn
,
519 const string
& _resource
,
521 param_vec_t
*extra_headers
,
522 RGWHTTPManager
*_mgr
) : RGWRESTSendResource(_conn
, "DELETE", _resource
,
523 params
, extra_headers
, _mgr
) {}