]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_rest_conn.cc
update sources to v12.1.2
[ceph.git] / ceph / src / rgw / rgw_rest_conn.cc
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#include "rgw_rados.h"
5#include "rgw_rest_conn.h"
6
7#define dout_subsys ceph_subsys_rgw
8
9RGWRESTConn::RGWRESTConn(CephContext *_cct, RGWRados *store,
10 const string& _remote_id,
11 const list<string>& remote_endpoints)
12 : cct(_cct),
13 endpoints(remote_endpoints.begin(), remote_endpoints.end()),
14 remote_id(_remote_id)
15{
16 if (store) {
17 key = store->get_zone_params().system_key;
18 self_zone_group = store->get_zonegroup().get_id();
19 }
20}
21
22RGWRESTConn::RGWRESTConn(RGWRESTConn&& other)
23 : cct(other.cct),
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())
29{
30}
31
32RGWRESTConn& RGWRESTConn::operator=(RGWRESTConn&& other)
33{
34 cct = other.cct;
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();
40 return *this;
41}
42
43int RGWRESTConn::get_url(string& endpoint)
44{
45 if (endpoints.empty()) {
46 ldout(cct, 0) << "ERROR: endpoints not configured for upstream zone" << dendl;
47 return -EIO;
48 }
49
50 int i = ++counter;
51 endpoint = endpoints[i % endpoints.size()];
52
53 return 0;
54}
55
56string RGWRESTConn::get_url()
57{
58 string endpoint;
59 if (endpoints.empty()) {
60 ldout(cct, 0) << "WARNING: endpoints not configured for upstream zone" << dendl; /* we'll catch this later */
61 return endpoint;
62 }
63
64 int i = ++counter;
65 endpoint = endpoints[i % endpoints.size()];
66
67 return endpoint;
68}
69
70static void populate_params(param_vec_t& params, const rgw_user *uid, const string& zonegroup)
71{
72 if (uid) {
73 string uid_str = uid->to_str();
74 if (!uid->empty()) {
75 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "uid", uid_str));
76 }
77 }
78 if (!zonegroup.empty()) {
79 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "zonegroup", zonegroup));
80 }
81}
82
83int RGWRESTConn::forward(const rgw_user& uid, req_info& info, obj_version *objv, size_t max_response, bufferlist *inbl, bufferlist *outbl)
84{
85 string url;
86 int ret = get_url(url);
87 if (ret < 0)
88 return ret;
89 param_vec_t params;
90 populate_params(params, &uid, self_zone_group);
91 if (objv) {
92 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "tag", objv->tag));
93 char buf[16];
94 snprintf(buf, sizeof(buf), "%lld", (long long)objv->ver);
95 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "ver", buf));
96 }
97 RGWRESTSimpleRequest req(cct, url, NULL, &params);
98 return req.forward_request(key, info, max_response, inbl, outbl);
99}
100
101class StreamObjData : public RGWGetDataCB {
102 rgw_obj obj;
103public:
104 explicit StreamObjData(rgw_obj& _obj) : obj(_obj) {}
105};
106
107int RGWRESTConn::put_obj_init(const rgw_user& uid, rgw_obj& obj, uint64_t obj_size,
108 map<string, bufferlist>& attrs, RGWRESTStreamWriteRequest **req)
109{
110 string url;
111 int ret = get_url(url);
112 if (ret < 0)
113 return ret;
114
115 param_vec_t params;
116 populate_params(params, &uid, self_zone_group);
c07f9fc5
FG
117 RGWRESTStreamWriteRequest *wr = new RGWRESTStreamWriteRequest(cct, url, NULL, &params);
118 ret = wr->put_obj_init(key, obj, obj_size, attrs);
119 if (ret < 0) {
120 delete wr;
121 return ret;
122 }
123 *req = wr;
124 return 0;
7c673cae
FG
125}
126
127int RGWRESTConn::complete_request(RGWRESTStreamWriteRequest *req, string& etag, real_time *mtime)
128{
129 int ret = req->complete(etag, mtime);
130 delete req;
131
132 return ret;
133}
134
135static void set_date_header(const real_time *t, map<string, string>& headers, const string& header_name)
136{
137 if (!t) {
138 return;
139 }
140 stringstream s;
141 utime_t tm = utime_t(*t);
142 tm.gmtime_nsec(s);
143 headers[header_name] = s.str();
144}
145
146template <class T>
147static void set_header(T val, map<string, string>& headers, const string& header_name)
148{
149 stringstream s;
150 s << val;
151 headers[header_name] = s.str();
152}
153
154
155int RGWRESTConn::get_obj(const rgw_user& uid, req_info *info /* optional */, rgw_obj& obj,
156 const real_time *mod_ptr, const real_time *unmod_ptr,
157 uint32_t mod_zone_id, uint64_t mod_pg_ver,
158 bool prepend_metadata, bool get_op, bool rgwx_stat,
159 bool sync_manifest, RGWGetDataCB *cb,
160 RGWRESTStreamRWRequest **req)
161{
162 string url;
163 int ret = get_url(url);
164 if (ret < 0)
165 return ret;
166
167 param_vec_t params;
168 populate_params(params, &uid, self_zone_group);
169 if (prepend_metadata) {
170 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "prepend-metadata", self_zone_group));
171 }
172 if (rgwx_stat) {
173 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "stat", "true"));
174 }
175 if (sync_manifest) {
176 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "sync-manifest", ""));
177 }
178 if (!obj.key.instance.empty()) {
179 const string& instance = obj.key.instance;
180 params.push_back(param_pair_t("versionId", instance));
181 }
182 if (get_op) {
183 *req = new RGWRESTStreamReadRequest(cct, url, cb, NULL, &params);
184 } else {
185 *req = new RGWRESTStreamHeadRequest(cct, url, cb, NULL, &params);
186 }
187 map<string, string> extra_headers;
188 if (info) {
31f18b77 189 const auto& orig_map = info->env->get_map();
7c673cae
FG
190
191 /* add original headers that start with HTTP_X_AMZ_ */
31f18b77
FG
192 static constexpr char SEARCH_AMZ_PREFIX[] = "HTTP_X_AMZ_";
193 for (auto iter= orig_map.lower_bound(SEARCH_AMZ_PREFIX); iter != orig_map.end(); ++iter) {
7c673cae
FG
194 const string& name = iter->first;
195 if (name == "HTTP_X_AMZ_DATE") /* dont forward date from original request */
196 continue;
31f18b77 197 if (name.compare(0, strlen(SEARCH_AMZ_PREFIX), SEARCH_AMZ_PREFIX) != 0)
7c673cae
FG
198 break;
199 extra_headers[iter->first] = iter->second;
200 }
201 }
202
203 set_date_header(mod_ptr, extra_headers, "HTTP_IF_MODIFIED_SINCE");
204 set_date_header(unmod_ptr, extra_headers, "HTTP_IF_UNMODIFIED_SINCE");
205 if (mod_zone_id != 0) {
206 set_header(mod_zone_id, extra_headers, "HTTP_DEST_ZONE_SHORT_ID");
207 }
208 if (mod_pg_ver != 0) {
209 set_header(mod_pg_ver, extra_headers, "HTTP_DEST_PG_VER");
210 }
211
31f18b77 212 int r = (*req)->send_request(key, extra_headers, obj);
7c673cae
FG
213 if (r < 0) {
214 delete *req;
215 *req = nullptr;
216 }
217
218 return r;
219}
220
221int RGWRESTConn::complete_request(RGWRESTStreamRWRequest *req, string& etag, real_time *mtime,
222 uint64_t *psize, map<string, string>& attrs)
223{
31f18b77 224 int ret = req->complete_request(etag, mtime, psize, attrs);
7c673cae
FG
225 delete req;
226
227 return ret;
228}
229
230int RGWRESTConn::get_resource(const string& resource,
231 param_vec_t *extra_params,
232 map<string, string> *extra_headers,
233 bufferlist& bl,
31f18b77 234 bufferlist *send_data,
7c673cae
FG
235 RGWHTTPManager *mgr)
236{
237 string url;
238 int ret = get_url(url);
239 if (ret < 0)
240 return ret;
241
242 param_vec_t params;
243
244 if (extra_params) {
245 params.insert(params.end(), extra_params->begin(), extra_params->end());
246 }
247
248 populate_params(params, nullptr, self_zone_group);
249
250 RGWStreamIntoBufferlist cb(bl);
251
252 RGWRESTStreamReadRequest req(cct, url, &cb, NULL, &params);
253
254 map<string, string> headers;
255 if (extra_headers) {
256 headers.insert(extra_headers->begin(), extra_headers->end());
257 }
258
31f18b77 259 ret = req.send_request(&key, headers, resource, send_data, mgr);
7c673cae 260 if (ret < 0) {
31f18b77 261 ldout(cct, 5) << __func__ << ": send_request() resource=" << resource << " returned ret=" << ret << dendl;
7c673cae
FG
262 return ret;
263 }
264
265 string etag;
266 map<string, string> attrs;
31f18b77 267 return req.complete_request(etag, NULL, NULL, attrs);
7c673cae
FG
268}
269
270RGWRESTReadResource::RGWRESTReadResource(RGWRESTConn *_conn,
271 const string& _resource,
272 const rgw_http_param_pair *pp,
273 param_vec_t *extra_headers,
274 RGWHTTPManager *_mgr)
275 : cct(_conn->get_ctx()), conn(_conn), resource(_resource),
276 params(make_param_list(pp)), cb(bl), mgr(_mgr),
277 req(cct, conn->get_url(), &cb, NULL, NULL)
278{
279 init_common(extra_headers);
280}
281
282RGWRESTReadResource::RGWRESTReadResource(RGWRESTConn *_conn,
283 const string& _resource,
284 param_vec_t& _params,
285 param_vec_t *extra_headers,
286 RGWHTTPManager *_mgr)
287 : cct(_conn->get_ctx()), conn(_conn), resource(_resource), params(_params),
288 cb(bl), mgr(_mgr), req(cct, conn->get_url(), &cb, NULL, NULL)
289{
290 init_common(extra_headers);
291}
292
293void RGWRESTReadResource::init_common(param_vec_t *extra_headers)
294{
295 populate_params(params, nullptr, conn->get_self_zonegroup());
296
297 if (extra_headers) {
298 headers.insert(extra_headers->begin(), extra_headers->end());
299 }
300
301 req.set_params(&params);
302}
303
304int RGWRESTReadResource::read()
305{
31f18b77 306 int ret = req.send_request(&conn->get_key(), headers, resource, nullptr, mgr);
7c673cae 307 if (ret < 0) {
31f18b77 308 ldout(cct, 5) << __func__ << ": send_request() resource=" << resource << " returned ret=" << ret << dendl;
7c673cae
FG
309 return ret;
310 }
311
312 string etag;
313 map<string, string> attrs;
31f18b77 314 return req.complete_request(etag, NULL, NULL, attrs);
7c673cae
FG
315}
316
317int RGWRESTReadResource::aio_read()
318{
31f18b77 319 int ret = req.send_request(&conn->get_key(), headers, resource, nullptr, mgr);
7c673cae 320 if (ret < 0) {
31f18b77 321 ldout(cct, 5) << __func__ << ": send_request() resource=" << resource << " returned ret=" << ret << dendl;
7c673cae
FG
322 return ret;
323 }
324
325 return 0;
326}
327
328RGWRESTSendResource::RGWRESTSendResource(RGWRESTConn *_conn,
329 const string& _method,
330 const string& _resource,
331 const rgw_http_param_pair *pp,
332 param_vec_t *extra_headers,
333 RGWHTTPManager *_mgr)
334 : cct(_conn->get_ctx()), conn(_conn), method(_method), resource(_resource),
335 params(make_param_list(pp)), cb(bl), mgr(_mgr),
336 req(cct, method.c_str(), conn->get_url(), &cb, NULL, NULL)
337{
338 init_common(extra_headers);
339}
340
341RGWRESTSendResource::RGWRESTSendResource(RGWRESTConn *_conn,
342 const string& _method,
343 const string& _resource,
344 param_vec_t& params,
345 param_vec_t *extra_headers,
346 RGWHTTPManager *_mgr)
347 : cct(_conn->get_ctx()), conn(_conn), method(_method), resource(_resource), params(params),
348 cb(bl), mgr(_mgr), req(cct, method.c_str(), conn->get_url(), &cb, NULL, NULL)
349{
350 init_common(extra_headers);
351}
352
353void RGWRESTSendResource::init_common(param_vec_t *extra_headers)
354{
355 populate_params(params, nullptr, conn->get_self_zonegroup());
356
357 if (extra_headers) {
358 headers.insert(extra_headers->begin(), extra_headers->end());
359 }
360
361 req.set_params(&params);
362}
363
364int RGWRESTSendResource::send(bufferlist& outbl)
365{
366 req.set_outbl(outbl);
31f18b77 367 int ret = req.send_request(&conn->get_key(), headers, resource, nullptr, mgr);
7c673cae 368 if (ret < 0) {
31f18b77 369 ldout(cct, 5) << __func__ << ": send_request() resource=" << resource << " returned ret=" << ret << dendl;
7c673cae
FG
370 return ret;
371 }
372
373 string etag;
374 map<string, string> attrs;
31f18b77 375 return req.complete_request(etag, NULL, NULL, attrs);
7c673cae
FG
376}
377
378int RGWRESTSendResource::aio_send(bufferlist& outbl)
379{
380 req.set_outbl(outbl);
31f18b77 381 int ret = req.send_request(&conn->get_key(), headers, resource, nullptr, mgr);
7c673cae 382 if (ret < 0) {
31f18b77 383 ldout(cct, 5) << __func__ << ": send_request() resource=" << resource << " returned ret=" << ret << dendl;
7c673cae
FG
384 return ret;
385 }
386
387 return 0;
388}
389