encode_json("api_name", api_name, f);
encode_json("is_master", is_master, f);
encode_json("endpoints", endpoints, f);
+ encode_json("hostnames", hostnames, f);
encode_json("master_zone", master_zone, f);
encode_json_map("zones", zones, f); /* more friendly representation */
encode_json_map("placement_targets", placement_targets, f); /* more friendly representation */
JSONDecoder::decode_json("api_name", api_name, obj);
JSONDecoder::decode_json("is_master", is_master, obj);
JSONDecoder::decode_json("endpoints", endpoints, obj);
+ JSONDecoder::decode_json("hostnames", hostnames, obj);
JSONDecoder::decode_json("master_zone", master_zone, obj);
JSONDecoder::decode_json("zones", zones, decode_zones, obj);
JSONDecoder::decode_json("placement_targets", placement_targets, decode_placement_targets, obj);
map<string, RGWRegionPlacementTarget> placement_targets;
string default_placement;
+ list<string> hostnames;
+
CephContext *cct;
RGWRados *store;
RGWRegion() : is_master(false), cct(NULL), store(NULL) {}
void encode(bufferlist& bl) const {
- ENCODE_START(1, 1, bl);
+ ENCODE_START(2, 1, bl);
::encode(name, bl);
::encode(api_name, bl);
::encode(is_master, bl);
::encode(zones, bl);
::encode(placement_targets, bl);
::encode(default_placement, bl);
+ ::encode(hostnames, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator& bl) {
- DECODE_START(1, bl);
+ DECODE_START(2, bl);
::decode(name, bl);
::decode(api_name, bl);
::decode(is_master, bl);
::decode(zones, bl);
::decode(placement_targets, bl);
::decode(default_placement, bl);
+ if (struct_v >= 2) {
+ ::decode(hostnames, bl);
+ }
DECODE_FINISH(bl);
}
return string(buf);
}
-void rgw_rest_init(CephContext *cct)
+static list<string> hostnames_list;
+
+void rgw_rest_init(CephContext *cct, RGWRegion& region)
{
for (struct rgw_http_attr *attr = rgw_to_http_attr_list; attr->rgw_attr; attr++) {
rgw_to_http_attrs[attr->rgw_attr] = attr->http_attr;
for (const struct rgw_http_status_code *h = http_codes; h->code; h++) {
http_status_names[h->code] = h->name;
}
+
+ /* avoid duplicate hostnames in hostnames list */
+ map<string, bool> hostnames_map;
+ if (!cct->_conf->rgw_dns_name.empty()) {
+ hostnames_map[cct->_conf->rgw_dns_name] = true;
+ }
+ for (list<string>::iterator iter = region.hostnames.begin(); iter != region.hostnames.end(); ++iter) {
+ hostnames_map[*iter] = true;
+ }
+
+ for (map<string, bool>::iterator iter = hostnames_map.begin(); iter != hostnames_map.end(); ++iter) {
+ hostnames_list.push_back(iter->first);
+ }
+}
+
+static bool str_ends_with(const string& s, const string& suffix, size_t *pos)
+{
+ size_t len = suffix.size();
+ if (len > (size_t)s.size()) {
+ return false;
+ }
+
+ ssize_t p = s.size() - len;
+ if (pos) {
+ *pos = p;
+ }
+
+ return s.compare(p, len, suffix) == 0;
+}
+
+static bool rgw_find_host_in_domains(const string& host, string *domain, string *subdomain)
+{
+ list<string>::iterator iter;
+ for (iter = hostnames_list.begin(); iter != hostnames_list.end(); ++iter) {
+ size_t pos;
+ if (!str_ends_with(host, *iter, &pos))
+ continue;
+
+ *domain = host.substr(pos);
+ if (pos == 0) {
+ subdomain->clear();
+ } else {
+ if (host[pos - 1] != '.') {
+ continue;
+ }
+
+ *domain = host.substr(pos);
+ *subdomain = host.substr(0, pos - 1);
+ }
+ return true;
+ }
+ return false;
}
static void dump_status(struct req_state *s, const char *status, const char *status_name)
req_info& info = s->info;
s->cio = cio;
- if (g_conf->rgw_dns_name.length() && info.host) {
+ if (info.host) {
string h(s->info.host);
- ldout(s->cct, 10) << "host=" << s->info.host << " rgw_dns_name=" << g_conf->rgw_dns_name << dendl;
- int pos = h.find(g_conf->rgw_dns_name);
+ ldout(s->cct, 10) << "host=" << s->info.host << dendl;
+ string domain;
+ string subdomain;
+ bool in_hosted_domain = rgw_find_host_in_domains(h, &domain, &subdomain);
+ ldout(s->cct, 20) << "subdomain=" << subdomain << " domain=" << domain << " in_hosted_domain=" << in_hosted_domain << dendl;
- if (g_conf->rgw_resolve_cname && pos < 0) {
+ if (g_conf->rgw_resolve_cname && !in_hosted_domain) {
string cname;
bool found;
int r = rgw_resolver->resolve_cname(h, cname, &found);
if (r < 0) {
- dout(0) << "WARNING: rgw_resolver->resolve_cname() returned r=" << r << dendl;
+ ldout(s->cct, 0) << "WARNING: rgw_resolver->resolve_cname() returned r=" << r << dendl;
}
if (found) {
- dout(0) << "resolved host cname " << h << " -> " << cname << dendl;
- h = cname;
- pos = h.find(g_conf->rgw_dns_name);
+ ldout(s->cct, 5) << "resolved host cname " << h << " -> " << cname << dendl;
+ in_hosted_domain = rgw_find_host_in_domains(cname, &domain, &subdomain);
+ ldout(s->cct, 20) << "subdomain=" << subdomain << " domain=" << domain << " in_hosted_domain=" << in_hosted_domain << dendl;
}
}
- if (pos > 0 && h[pos - 1] == '.') {
+ if (in_hosted_domain && !subdomain.empty()) {
string encoded_bucket = "/";
- encoded_bucket.append(h.substr(0, pos-1));
+ encoded_bucket.append(subdomain);
if (s->info.request_uri[0] != '/')
- encoded_bucket.append("/'");
+ encoded_bucket.append("/'");
encoded_bucket.append(s->info.request_uri);
s->info.request_uri = encoded_bucket;
}
+
+ if (!domain.empty()) {
+ s->info.domain = domain;
+ }
+ }
+
+ if (s->info.domain.empty()) {
+ s->info.domain = s->cct->_conf->rgw_dns_name;
}
url_decode(s->info.request_uri, s->decoded_uri);