Skip to content

Commit 36583eb

Browse files
committed
rgw/rest: RGWRESTConn::forward() prefers to return http errors
callers need to distinguish between transport errors (a failure to forward the request) and http errors (successfully forwarded and got a response). forward() was losing this information by mapping any http errors to errnos use tl::expected to differentiate between transport errors and http errors, with the latter being the successful/expected case Signed-off-by: Casey Bodley <[email protected]>
1 parent 46d6f81 commit 36583eb

File tree

8 files changed

+100
-59
lines changed

8 files changed

+100
-59
lines changed

src/rgw/radosgw-admin/radosgw-admin.cc

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,14 +1902,21 @@ static int send_to_remote_gateway(RGWRESTConn* conn, req_info& info,
19021902

19031903
ceph::bufferlist response;
19041904
rgw_user user;
1905-
int ret = conn->forward(dpp(), user, info, MAX_REST_RESPONSE, &in_data, &response, null_yield);
1905+
auto result = conn->forward(dpp(), user, info, MAX_REST_RESPONSE, &in_data, &response, null_yield);
1906+
if (!result) {
1907+
return result.error();
1908+
}
1909+
int ret = rgw_http_error_to_errno(*result);
1910+
if (ret < 0) {
1911+
return ret;
1912+
}
19061913

1907-
int parse_ret = parser.parse(response.c_str(), response.length());
1908-
if (parse_ret < 0) {
1914+
ret = parser.parse(response.c_str(), response.length());
1915+
if (ret < 0) {
19091916
cerr << "failed to parse response" << std::endl;
1910-
return parse_ret;
1917+
return ret;
19111918
}
1912-
return ret;
1919+
return 0;
19131920
}
19141921

19151922
static int send_to_url(const string& url,
@@ -1930,14 +1937,21 @@ static int send_to_url(const string& url,
19301937
RGWRESTSimpleRequest req(g_ceph_context, info.method, url, NULL, &params, opt_region);
19311938

19321939
bufferlist response;
1933-
int ret = req.forward_request(dpp(), key, info, MAX_REST_RESPONSE, &in_data, &response, null_yield);
1940+
auto result = req.forward_request(dpp(), key, info, MAX_REST_RESPONSE, &in_data, &response, null_yield);
1941+
if (!result) {
1942+
return result.error();
1943+
}
1944+
int ret = rgw_http_error_to_errno(*result);
1945+
if (ret < 0) {
1946+
return ret;
1947+
}
19341948

1935-
int parse_ret = parser.parse(response.c_str(), response.length());
1936-
if (parse_ret < 0) {
1949+
ret = parser.parse(response.c_str(), response.length());
1950+
if (ret < 0) {
19371951
cout << "failed to parse response" << std::endl;
1938-
return parse_ret;
1952+
return ret;
19391953
}
1940-
return ret;
1954+
return 0;
19411955
}
19421956

19431957
static int send_to_remote_or_url(RGWRESTConn *conn, const string& url,

src/rgw/rgw_op.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,12 @@ int rgw_forward_request_to_master(const DoutPrefixProvider* dpp,
155155
creds, site.get_zonegroup().id, zg->second.api_name};
156156
bufferlist outdata;
157157
constexpr size_t max_response_size = 128 * 1024; // we expect a very small response
158-
int ret = conn.forward(dpp, effective_owner, req,
159-
max_response_size, indata, &outdata, y);
158+
auto result = conn.forward(dpp, effective_owner, req,
159+
max_response_size, indata, &outdata, y);
160+
if (!result) {
161+
return result.error();
162+
}
163+
int ret = rgw_http_error_to_errno(*result);
160164
if (ret < 0) {
161165
return ret;
162166
}

src/rgw/rgw_period_puller.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "rgw_rados.h"
55
#include "rgw_zone.h"
66
#include "rgw_rest_conn.h"
7+
#include "rgw_http_errors.h"
78
#include "common/ceph_json.h"
89
#include "common/errno.h"
910

@@ -40,7 +41,11 @@ int pull_period(const DoutPrefixProvider *dpp, RGWRESTConn* conn, const std::str
4041

4142
bufferlist data;
4243
#define MAX_REST_RESPONSE (128 * 1024)
43-
int r = conn->forward(dpp, user, info, MAX_REST_RESPONSE, nullptr, &data, y);
44+
auto result = conn->forward(dpp, user, info, MAX_REST_RESPONSE, nullptr, &data, y);
45+
if (!result) {
46+
return result.error();
47+
}
48+
int r = rgw_http_error_to_errno(*result);
4449
if (r < 0) {
4550
return r;
4651
}

src/rgw/rgw_rest_client.cc

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,8 @@ static void scope_from_api_name(const DoutPrefixProvider *dpp,
364364
}
365365
}
366366

367-
int RGWRESTSimpleRequest::forward_request(const DoutPrefixProvider *dpp, const RGWAccessKey& key, const req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl, optional_yield y, std::string service)
367+
auto RGWRESTSimpleRequest::forward_request(const DoutPrefixProvider *dpp, const RGWAccessKey& key, const req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl, optional_yield y, std::string service)
368+
-> tl::expected<int, int>
368369
{
369370

370371
string date_str;
@@ -410,7 +411,7 @@ int RGWRESTSimpleRequest::forward_request(const DoutPrefixProvider *dpp, const R
410411
int ret = sign_request(dpp, key, region, s, new_env, new_info, nullptr);
411412
if (ret < 0) {
412413
ldpp_dout(dpp, 0) << "ERROR: failed to sign request" << dendl;
413-
return ret;
414+
return tl::unexpected(ret);
414415
}
415416

416417
if (s == "iam") {
@@ -452,13 +453,11 @@ int RGWRESTSimpleRequest::forward_request(const DoutPrefixProvider *dpp, const R
452453
method = new_info.method;
453454
url = new_url;
454455

455-
int r = process(dpp, y);
456-
if (r < 0) {
457-
if (http_status == 0) {
458-
// no http status, generally means the service is not available
459-
r = -ERR_SERVICE_UNAVAILABLE;
460-
}
461-
return r;
456+
std::ignore = process(dpp, y);
457+
458+
if (http_status == 0) {
459+
// no http status, generally means the service is not available
460+
return tl::unexpected(-ERR_SERVICE_UNAVAILABLE);
462461
}
463462

464463
response.append((char)0); /* NULL terminate response */
@@ -467,7 +466,7 @@ int RGWRESTSimpleRequest::forward_request(const DoutPrefixProvider *dpp, const R
467466
*outbl = std::move(response);
468467
}
469468

470-
return status;
469+
return http_status;
471470
}
472471

473472
class RGWRESTStreamOutCB : public RGWGetDataCB {

src/rgw/rgw_rest_client.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#pragma once
55

6+
#include "include/expected.hpp"
67
#include "rgw_http_client.h"
78

89
class RGWGetDataCB;
@@ -65,7 +66,9 @@ class RGWRESTSimpleRequest : public RGWHTTPSimpleRequest {
6566
param_vec_t *_headers, param_vec_t *_params,
6667
std::optional<std::string> _api_name) : RGWHTTPSimpleRequest(_cct, _method, _url, _headers, _params), api_name(_api_name) {}
6768

68-
int forward_request(const DoutPrefixProvider *dpp, const RGWAccessKey& key, const req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl, optional_yield y, std::string service="");
69+
// return the http status of the response or an error code from the transport
70+
auto forward_request(const DoutPrefixProvider *dpp, const RGWAccessKey& key, const req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl, optional_yield y, std::string service="")
71+
-> tl::expected<int, int>;
6972
};
7073

7174
class RGWWriteDrainCB {

src/rgw/rgw_rest_conn.cc

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "rgw_zone.h"
55
#include "rgw_rest_conn.h"
6+
#include "rgw_http_errors.h"
67
#include "rgw_sal.h"
78
#include "rgw_rados.h"
89

@@ -153,57 +154,63 @@ void RGWRESTConn::populate_params(param_vec_t& params, const rgw_owner* uid, con
153154
populate_zonegroup(params, zonegroup);
154155
}
155156

156-
int RGWRESTConn::forward(const DoutPrefixProvider *dpp, const rgw_owner& uid, const req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl, optional_yield y)
157+
auto RGWRESTConn::forward(const DoutPrefixProvider *dpp, const rgw_owner& uid,
158+
const req_info& info, size_t max_response,
159+
bufferlist *inbl, bufferlist *outbl, optional_yield y)
160+
-> tl::expected<int, int>
157161
{
158-
int ret = 0;
159-
160162
static constexpr int NUM_ENPOINT_IOERROR_RETRIES = 20;
161163
for (int tries = 0; tries < NUM_ENPOINT_IOERROR_RETRIES; tries++) {
162164
string url;
163-
ret = get_url(url);
164-
if (ret < 0)
165-
return ret;
165+
int ret = get_url(url);
166+
if (ret < 0) {
167+
return tl::unexpected(ret);
168+
}
166169
param_vec_t params;
167170
populate_params(params, &uid, self_zone_group);
168171
RGWRESTSimpleRequest req(cct, info.method, url, NULL, &params, api_name);
169-
ret = req.forward_request(dpp, key, info, max_response, inbl, outbl, y);
170-
if (ret == -EIO) {
171-
set_url_unconnectable(url);
172-
if (tries < NUM_ENPOINT_IOERROR_RETRIES - 1) {
173-
ldpp_dout(dpp, 20) << __func__ << "(): failed to forward request. retries=" << tries << dendl;
174-
continue;
175-
}
172+
auto result = req.forward_request(dpp, key, info, max_response, inbl, outbl, y);
173+
if (result) {
174+
return result;
175+
} else if (result.error() != -EIO) {
176+
return result;
177+
}
178+
set_url_unconnectable(url);
179+
if (tries < NUM_ENPOINT_IOERROR_RETRIES - 1) {
180+
ldpp_dout(dpp, 20) << __func__ << "(): failed to forward request. retries=" << tries << dendl;
176181
}
177-
break;
178182
}
179-
return ret;
183+
return tl::unexpected(-EIO);
180184
}
181185

182-
int RGWRESTConn::forward_iam_request(const DoutPrefixProvider *dpp, const req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl, optional_yield y)
186+
auto RGWRESTConn::forward_iam(const DoutPrefixProvider *dpp, const req_info& info,
187+
size_t max_response, bufferlist *inbl,
188+
bufferlist *outbl, optional_yield y)
189+
-> tl::expected<int, int>
183190
{
184-
int ret = 0;
185-
186191
static constexpr int NUM_ENPOINT_IOERROR_RETRIES = 20;
187192
for (int tries = 0; tries < NUM_ENPOINT_IOERROR_RETRIES; tries++) {
188193
string url;
189-
ret = get_url(url);
190-
if (ret < 0)
191-
return ret;
194+
int ret = get_url(url);
195+
if (ret < 0) {
196+
return tl::unexpected(ret);
197+
}
192198
param_vec_t params;
193199
std::string service = "iam";
194200
RGWRESTSimpleRequest req(cct, info.method, url, NULL, &params, api_name);
195201
// coverity[uninit_use_in_call:SUPPRESS]
196-
ret = req.forward_request(dpp, key, info, max_response, inbl, outbl, y, service);
197-
if (ret == -EIO) {
198-
set_url_unconnectable(url);
199-
if (tries < NUM_ENPOINT_IOERROR_RETRIES - 1) {
200-
ldpp_dout(dpp, 20) << __func__ << "(): failed to forward request. retries=" << tries << dendl;
201-
continue;
202-
}
202+
auto result = req.forward_request(dpp, key, info, max_response, inbl, outbl, y, service);
203+
if (result) {
204+
return result;
205+
} else if (result.error() != -EIO) {
206+
return result;
207+
}
208+
set_url_unconnectable(url);
209+
if (tries < NUM_ENPOINT_IOERROR_RETRIES - 1) {
210+
ldpp_dout(dpp, 20) << __func__ << "(): failed to forward request. retries=" << tries << dendl;
203211
}
204-
break;
205212
}
206-
return ret;
213+
return tl::unexpected(-EIO);
207214
}
208215

209216
int RGWRESTConn::put_obj_send_init(const rgw_obj& obj, const rgw_http_param_pair *extra_params, RGWRESTStreamS3PutObj **req)

src/rgw/rgw_rest_conn.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,16 @@ class RGWRESTConn
130130
virtual void populate_params(param_vec_t& params, const rgw_owner* uid, const std::string& zonegroup);
131131

132132
/* sync request */
133-
int forward(const DoutPrefixProvider *dpp, const rgw_owner& uid, const req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl, optional_yield y);
133+
auto forward(const DoutPrefixProvider *dpp, const rgw_owner& uid,
134+
const req_info& info, size_t max_response,
135+
bufferlist *inbl, bufferlist *outbl, optional_yield y)
136+
-> tl::expected<int, int>;
134137

135138
/* sync request */
136-
int forward_iam_request(const DoutPrefixProvider *dpp, const req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl, optional_yield y);
137-
139+
auto forward_iam(const DoutPrefixProvider *dpp, const req_info& info,
140+
size_t max_response, bufferlist *inbl,
141+
bufferlist *outbl, optional_yield y)
142+
-> tl::expected<int, int>;
138143

139144
/* async requests */
140145
int put_obj_send_init(const rgw_obj& obj, const rgw_http_param_pair *extra_params, RGWRESTStreamS3PutObj **req);

src/rgw/rgw_rest_iam.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,12 @@ int forward_iam_request_to_master(const DoutPrefixProvider* dpp,
304304
std::move(creds), zg->second.id, zg->second.api_name};
305305
bufferlist outdata;
306306
constexpr size_t max_response_size = 128 * 1024; // we expect a very small response
307-
int ret = conn.forward_iam_request(dpp, req, max_response_size,
308-
&indata, &outdata, y);
307+
auto result = conn.forward_iam(dpp, req, max_response_size,
308+
&indata, &outdata, y);
309+
if (!result) {
310+
return result.error();
311+
}
312+
int ret = rgw_http_error_to_errno(*result);
309313
if (ret < 0) {
310314
return ret;
311315
}

0 commit comments

Comments
 (0)