verify_ssl(cct->_conf->rgw_verify_ssl),
cct(cct),
method(_method),
- endpoint_orig(_endpoint),
endpoint(_endpoint) {
init();
}
struct rgw_http_req_data;
class RGWHTTPManager;
+/**
+ * RGWEndpoint - Represents an HTTP endpoint with additional metdata such as connection routing.
+ *
+ * Unlike a plain URL string, RGWEndpoint carries additional information needed
+ * to leverage libcurl's CURLOPT_CONNECT_TO option. This enables RGW to route
+ * requests to specific IP addresses while preserving the original hostname for
+ * TLS/SNI and Host headers.
+ *
+ * Fields:
+ * - url: The effective URL for the request (may be modified with paths).
+ * - original_url: The initially configured endpoint URL (preserved for reference).
+ * - connect_to: libcurl CONNECT_TO string (format: "host:port:addr:port") to
+ * override connection routing without changing the request URL.
+ */
struct RGWEndpoint {
private:
std::string url;
+ std::string original_url;
std::string connect_to;
public:
RGWEndpoint(const char* u) : RGWEndpoint(std::string(u)) {}
RGWEndpoint(std::string u, std::string c = {})
- : url(std::move(u)), connect_to(std::move(c)) {}
+ : url(std::move(u)), original_url(url), connect_to(std::move(c)) {}
RGWEndpoint with_url(std::string new_url) const {
RGWEndpoint e = *this;
return e;
}
- void set_url(const std::string& _url) { url = _url; }
+ void set_url(const std::string& _url) {
+ url = _url;
+ // Capture the first URL assignment as the original
+ if (original_url.empty()) {
+ original_url = _url;
+ }
+ }
const std::string& get_url() const { return url; }
+ const std::string& get_original_url() const { return original_url; }
void set_connect_to(const std::string& _connect_to) { connect_to = _connect_to; }
const std::string& get_connect_to() const { return connect_to; }
CephContext *cct;
std::string method;
- RGWEndpoint endpoint_orig;
RGWEndpoint endpoint;
std::string protocol;
int get_req_retcode();
+ const RGWEndpoint& get_endpoint() const {
+ return endpoint;
+ }
+
void set_endpoint(const RGWEndpoint& _endpoint) {
endpoint = _endpoint;
}
endpoint.set_url(_url);
}
- const RGWEndpoint& get_endpoint_orig() const {
- return endpoint_orig;
- }
-
void set_method(const std::string& _method) {
method = _method;
}
void set_policy(const RGWAccessControlPolicy& policy);
int sign(const DoutPrefixProvider *dpp, RGWAccessKey& key, const bufferlist *opt_content);
- const RGWEndpoint& get_endpoint() { return endpoint; }
+ const RGWEndpoint& get_endpoint() const { return endpoint; }
};
class RGWHTTPStreamRWRequest : public RGWHTTPSimpleRequest {
void RGWRESTConn::set_endpoint_unconnectable(const RGWEndpoint& endpoint)
{
- const string& url = endpoint.get_url();
+ const string& orig_url = endpoint.get_original_url();
- if (url.empty() || resolved_endpoints.find(url) == resolved_endpoints.end()) {
- ldout(cct, 0) << "ERROR: endpoint is not a valid or doesn't have status. endpoint="
- << url << dendl;
+ if (orig_url.empty() || resolved_endpoints.find(orig_url) == resolved_endpoints.end()) {
+ ldout(cct, 0) << "ERROR: endpoint is not a valid or doesn't have status. "
+ << " original_url=" << orig_url << " current_url=" << endpoint.get_url() << dendl;
return;
}
- resolved_endpoints[url].status.store(ceph::real_clock::now());
+ resolved_endpoints[orig_url].status.store(ceph::real_clock::now());
- ldout(cct, 10) << "set endpoint unconnectable. url=" << url << dendl;
+ ldout(cct, 10) << "set endpoint unconnectable. url=" << orig_url << dendl;
}
void RGWRESTConn::populate_params(param_vec_t& params, const rgw_owner* uid, const string& zonegroup)
int ret = req->complete_request(dpp, y, &etag, mtime);
if (ret == -EIO) {
ldout(cct, 5) << __func__ << ": complete_request() returned ret=" << ret << dendl;
- set_endpoint_unconnectable(req->get_endpoint_orig());
+ set_endpoint_unconnectable(req->get_endpoint());
}
delete req;
int ret = req->complete_request(dpp, y, etag, mtime, psize, pattrs, pheaders);
if (ret == -EIO) {
ldout(cct, 5) << __func__ << ": complete_request() returned ret=" << ret << dendl;
- set_endpoint_unconnectable(req->get_endpoint_orig());
+ set_endpoint_unconnectable(req->get_endpoint());
}
delete req;
ret = req.complete_request(dpp, y);
if (ret == -EIO) {
- conn->set_endpoint_unconnectable(req.get_endpoint_orig());
+ conn->set_endpoint_unconnectable(req.get_endpoint());
ldpp_dout(dpp, 20) << __func__ << ": complete_request() returned ret=" << ret << dendl;
}
ret = req.complete_request(dpp, y);
if (ret == -EIO) {
- conn->set_endpoint_unconnectable(req.get_endpoint_orig());
+ conn->set_endpoint_unconnectable(req.get_endpoint());
ldpp_dout(dpp, 20) << __func__ << ": complete_request() returned ret=" << ret << dendl;
}
int ret = req.wait(dpp, y);
if (ret < 0) {
if (ret == -ERR_INTERNAL_ERROR) {
- conn->set_endpoint_unconnectable(req.get_endpoint_orig());
+ conn->set_endpoint_unconnectable(req.get_endpoint());
}
return ret;
}
int ret = req.wait(dpp, y);
if (ret < 0) {
if (ret == -ERR_INTERNAL_ERROR) {
- conn->set_endpoint_unconnectable(req.get_endpoint_orig());
+ conn->set_endpoint_unconnectable(req.get_endpoint());
}
return ret;
}
*pbl = bl;
if (ret == -ERR_INTERNAL_ERROR) {
- conn->set_endpoint_unconnectable(req.get_endpoint_orig());
+ conn->set_endpoint_unconnectable(req.get_endpoint());
}
if (ret < 0 && err_result ) {
{
int ret = req.wait(dpp, y);
if (ret == -ERR_INTERNAL_ERROR) {
- conn->set_endpoint_unconnectable(req.get_endpoint_orig());
+ conn->set_endpoint_unconnectable(req.get_endpoint());
}
if (ret >= 0) {