1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
5 #include "rgw_rest_conn.h"
7 #define dout_subsys ceph_subsys_rgw
9 RGWRESTConn::RGWRESTConn(CephContext
*_cct
, RGWRados
*store
,
10 const string
& _remote_id
,
11 const list
<string
>& remote_endpoints
)
13 endpoints(remote_endpoints
.begin(), remote_endpoints
.end()),
17 key
= store
->get_zone_params().system_key
;
18 self_zone_group
= store
->get_zonegroup().get_id();
22 RGWRESTConn::RGWRESTConn(RGWRESTConn
&& other
)
24 endpoints(std::move(other
.endpoints
)),
25 key(std::move(other
.key
)),
26 self_zone_group(std::move(other
.self_zone_group
)),
27 remote_id(std::move(other
.remote_id
)),
28 counter(other
.counter
.load())
32 RGWRESTConn
& RGWRESTConn::operator=(RGWRESTConn
&& other
)
35 endpoints
= std::move(other
.endpoints
);
36 key
= std::move(other
.key
);
37 self_zone_group
= std::move(other
.self_zone_group
);
38 remote_id
= std::move(other
.remote_id
);
39 counter
= other
.counter
.load();
43 int RGWRESTConn::get_url(string
& endpoint
)
45 if (endpoints
.empty()) {
46 ldout(cct
, 0) << "ERROR: endpoints not configured for upstream zone" << dendl
;
51 endpoint
= endpoints
[i
% endpoints
.size()];
56 string
RGWRESTConn::get_url()
59 if (endpoints
.empty()) {
60 ldout(cct
, 0) << "WARNING: endpoints not configured for upstream zone" << dendl
; /* we'll catch this later */
65 endpoint
= endpoints
[i
% endpoints
.size()];
70 static void populate_params(param_vec_t
& params
, const rgw_user
*uid
, const string
& zonegroup
)
73 string uid_str
= uid
->to_str();
75 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"uid", uid_str
));
78 if (!zonegroup
.empty()) {
79 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"zonegroup", zonegroup
));
83 int RGWRESTConn::forward(const rgw_user
& uid
, req_info
& info
, obj_version
*objv
, size_t max_response
, bufferlist
*inbl
, bufferlist
*outbl
)
86 int ret
= get_url(url
);
90 populate_params(params
, &uid
, self_zone_group
);
92 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"tag", objv
->tag
));
94 snprintf(buf
, sizeof(buf
), "%lld", (long long)objv
->ver
);
95 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"ver", buf
));
97 RGWRESTSimpleRequest
req(cct
, url
, NULL
, ¶ms
);
98 return req
.forward_request(key
, info
, max_response
, inbl
, outbl
);
101 class StreamObjData
: public RGWGetDataCB
{
104 explicit StreamObjData(rgw_obj
& _obj
) : obj(_obj
) {}
107 int RGWRESTConn::put_obj_init(const rgw_user
& uid
, rgw_obj
& obj
, uint64_t obj_size
,
108 map
<string
, bufferlist
>& attrs
, RGWRESTStreamWriteRequest
**req
)
111 int ret
= get_url(url
);
116 populate_params(params
, &uid
, self_zone_group
);
117 *req
= new RGWRESTStreamWriteRequest(cct
, url
, NULL
, ¶ms
);
118 return (*req
)->put_obj_init(key
, obj
, obj_size
, attrs
);
121 int RGWRESTConn::complete_request(RGWRESTStreamWriteRequest
*req
, string
& etag
, real_time
*mtime
)
123 int ret
= req
->complete(etag
, mtime
);
129 static void set_date_header(const real_time
*t
, map
<string
, string
>& headers
, const string
& header_name
)
135 utime_t tm
= utime_t(*t
);
137 headers
[header_name
] = s
.str();
141 static void set_header(T val
, map
<string
, string
>& headers
, const string
& header_name
)
145 headers
[header_name
] = s
.str();
149 int RGWRESTConn::get_obj(const rgw_user
& uid
, req_info
*info
/* optional */, rgw_obj
& obj
,
150 const real_time
*mod_ptr
, const 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
,
153 bool sync_manifest
, RGWGetDataCB
*cb
,
154 RGWRESTStreamRWRequest
**req
)
157 int ret
= get_url(url
);
162 populate_params(params
, &uid
, self_zone_group
);
163 if (prepend_metadata
) {
164 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"prepend-metadata", self_zone_group
));
167 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"stat", "true"));
170 params
.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX
"sync-manifest", ""));
172 if (!obj
.key
.instance
.empty()) {
173 const string
& instance
= obj
.key
.instance
;
174 params
.push_back(param_pair_t("versionId", instance
));
177 *req
= new RGWRESTStreamReadRequest(cct
, url
, cb
, NULL
, ¶ms
);
179 *req
= new RGWRESTStreamHeadRequest(cct
, url
, cb
, NULL
, ¶ms
);
181 map
<string
, string
> extra_headers
;
183 map
<string
, string
, ltstr_nocase
>& orig_map
= info
->env
->get_map();
185 /* add original headers that start with HTTP_X_AMZ_ */
186 #define SEARCH_AMZ_PREFIX "HTTP_X_AMZ_"
187 for (map
<string
, string
>::iterator iter
= orig_map
.lower_bound(SEARCH_AMZ_PREFIX
); iter
!= orig_map
.end(); ++iter
) {
188 const string
& name
= iter
->first
;
189 if (name
== "HTTP_X_AMZ_DATE") /* dont forward date from original request */
191 if (name
.compare(0, sizeof(SEARCH_AMZ_PREFIX
) - 1, "HTTP_X_AMZ_") != 0)
193 extra_headers
[iter
->first
] = iter
->second
;
197 set_date_header(mod_ptr
, extra_headers
, "HTTP_IF_MODIFIED_SINCE");
198 set_date_header(unmod_ptr
, extra_headers
, "HTTP_IF_UNMODIFIED_SINCE");
199 if (mod_zone_id
!= 0) {
200 set_header(mod_zone_id
, extra_headers
, "HTTP_DEST_ZONE_SHORT_ID");
202 if (mod_pg_ver
!= 0) {
203 set_header(mod_pg_ver
, extra_headers
, "HTTP_DEST_PG_VER");
206 int r
= (*req
)->get_obj(key
, extra_headers
, obj
);
215 int RGWRESTConn::complete_request(RGWRESTStreamRWRequest
*req
, string
& etag
, real_time
*mtime
,
216 uint64_t *psize
, map
<string
, string
>& attrs
)
218 int ret
= req
->complete(etag
, mtime
, psize
, attrs
);
224 int RGWRESTConn::get_resource(const string
& resource
,
225 param_vec_t
*extra_params
,
226 map
<string
, string
> *extra_headers
,
231 int ret
= get_url(url
);
238 params
.insert(params
.end(), extra_params
->begin(), extra_params
->end());
241 populate_params(params
, nullptr, self_zone_group
);
243 RGWStreamIntoBufferlist
cb(bl
);
245 RGWRESTStreamReadRequest
req(cct
, url
, &cb
, NULL
, ¶ms
);
247 map
<string
, string
> headers
;
249 headers
.insert(extra_headers
->begin(), extra_headers
->end());
252 ret
= req
.get_resource(key
, headers
, resource
, mgr
);
254 ldout(cct
, 5) << __func__
<< ": get_resource() resource=" << resource
<< " returned ret=" << ret
<< dendl
;
259 map
<string
, string
> attrs
;
260 return req
.complete(etag
, NULL
, NULL
, attrs
);
263 RGWRESTReadResource::RGWRESTReadResource(RGWRESTConn
*_conn
,
264 const string
& _resource
,
265 const rgw_http_param_pair
*pp
,
266 param_vec_t
*extra_headers
,
267 RGWHTTPManager
*_mgr
)
268 : cct(_conn
->get_ctx()), conn(_conn
), resource(_resource
),
269 params(make_param_list(pp
)), cb(bl
), mgr(_mgr
),
270 req(cct
, conn
->get_url(), &cb
, NULL
, NULL
)
272 init_common(extra_headers
);
275 RGWRESTReadResource::RGWRESTReadResource(RGWRESTConn
*_conn
,
276 const string
& _resource
,
277 param_vec_t
& _params
,
278 param_vec_t
*extra_headers
,
279 RGWHTTPManager
*_mgr
)
280 : cct(_conn
->get_ctx()), conn(_conn
), resource(_resource
), params(_params
),
281 cb(bl
), mgr(_mgr
), req(cct
, conn
->get_url(), &cb
, NULL
, NULL
)
283 init_common(extra_headers
);
286 void RGWRESTReadResource::init_common(param_vec_t
*extra_headers
)
288 populate_params(params
, nullptr, conn
->get_self_zonegroup());
291 headers
.insert(extra_headers
->begin(), extra_headers
->end());
294 req
.set_params(¶ms
);
297 int RGWRESTReadResource::read()
299 int ret
= req
.get_resource(conn
->get_key(), headers
, resource
, mgr
);
301 ldout(cct
, 5) << __func__
<< ": get_resource() resource=" << resource
<< " returned ret=" << ret
<< dendl
;
306 map
<string
, string
> attrs
;
307 return req
.complete(etag
, NULL
, NULL
, attrs
);
310 int RGWRESTReadResource::aio_read()
312 int ret
= req
.get_resource(conn
->get_key(), headers
, resource
, mgr
);
314 ldout(cct
, 5) << __func__
<< ": get_resource() resource=" << resource
<< " returned ret=" << ret
<< dendl
;
321 RGWRESTSendResource::RGWRESTSendResource(RGWRESTConn
*_conn
,
322 const string
& _method
,
323 const string
& _resource
,
324 const rgw_http_param_pair
*pp
,
325 param_vec_t
*extra_headers
,
326 RGWHTTPManager
*_mgr
)
327 : cct(_conn
->get_ctx()), conn(_conn
), method(_method
), resource(_resource
),
328 params(make_param_list(pp
)), cb(bl
), mgr(_mgr
),
329 req(cct
, method
.c_str(), conn
->get_url(), &cb
, NULL
, NULL
)
331 init_common(extra_headers
);
334 RGWRESTSendResource::RGWRESTSendResource(RGWRESTConn
*_conn
,
335 const string
& _method
,
336 const string
& _resource
,
338 param_vec_t
*extra_headers
,
339 RGWHTTPManager
*_mgr
)
340 : cct(_conn
->get_ctx()), conn(_conn
), method(_method
), resource(_resource
), params(params
),
341 cb(bl
), mgr(_mgr
), req(cct
, method
.c_str(), conn
->get_url(), &cb
, NULL
, NULL
)
343 init_common(extra_headers
);
346 void RGWRESTSendResource::init_common(param_vec_t
*extra_headers
)
348 populate_params(params
, nullptr, conn
->get_self_zonegroup());
351 headers
.insert(extra_headers
->begin(), extra_headers
->end());
354 req
.set_params(¶ms
);
357 int RGWRESTSendResource::send(bufferlist
& outbl
)
359 req
.set_outbl(outbl
);
360 int ret
= req
.get_resource(conn
->get_key(), headers
, resource
, mgr
);
362 ldout(cct
, 5) << __func__
<< ": get_resource() resource=" << resource
<< " returned ret=" << ret
<< dendl
;
367 map
<string
, string
> attrs
;
368 return req
.complete(etag
, NULL
, NULL
, attrs
);
371 int RGWRESTSendResource::aio_send(bufferlist
& outbl
)
373 req
.set_outbl(outbl
);
374 int ret
= req
.get_resource(conn
->get_key(), headers
, resource
, mgr
);
376 ldout(cct
, 5) << __func__
<< ": get_resource() resource=" << resource
<< " returned ret=" << ret
<< dendl
;