rgw v2签名生成过程

本文详细介绍了RESTful API请求的构建过程,包括URL参数设置、额外头部信息处理以及请求发送前的准备步骤。代码示例展示了如何构造请求、设置HTTP头以及处理自定义元数据。此外,还涉及了日期和时间戳在认证头中的重要性以及如何验证Content-MD5。
摘要由CSDN通过智能技术生成
/*
url=ip:port
param_vec_t params;
params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "prepend-metadata", "true"));
params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "stat", "true"));
params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "sync-manifest", ""));
if (!obj.key.instance.empty()) {
  const string& instance = obj.key.instance;
  params.push_back(param_pair_t("versionId", instance));
}
*/
// 构造
*req = new RGWRESTStreamReadRequest(cct, url, in_params.cb, NULL, &params, host_style);

/*
// for copy, get  original headers that start with HTTP_X_AMZ_
map<string, string> extra_headers;
if (info) {
  map<string, string, ltstr_nocase>& orig_map = info->env->get_map();

  #define SEARCH_AMZ_PREFIX "HTTP_X_AMZ_"
  for (map<string, string>::iterator iter = orig_map.lower_bound(SEARCH_AMZ_PREFIX); iter != orig_map.end(); ++iter) {
    const string& name = iter->first;
    if (name == "HTTP_X_AMZ_DATE") /* dont forward date from original request */
      continue;
    if (name.compare(0, sizeof(SEARCH_AMZ_PREFIX) - 1, "HTTP_X_AMZ_") != 0)
      break;
    extra_headers[iter->first] = iter->second;
  }
}
*/
// 发送准备
int RGWRESTStreamRWRequest::send_prepare(RGWAccessKey& key, map<string, string>& extra_headers, const rgw_obj& obj)
{
  string resource;
  send_prepare_convert(obj, &resource);   

  return do_send_prepare(&key, extra_headers, resource);
}

// resource=bk/obj
int RGWRESTStreamRWRequest::do_send_prepare(RGWAccessKey *key, map<string, string>& extra_headers, const string& resource, bufferlist *send_data)
{
  string new_url = url;
  if (new_url[new_url.size() - 1] != '/')
    new_url.append("/");          // ip:port/
  
  string new_resource;
  if (resource[0] == '/') {
    new_resource = resource.substr(1);
  } else {
    new_resource = resource;        // bk/obj
  }

  RGWEnv new_env;
  req_info new_info(cct, &new_env);
  RGWRESTGenerateHTTPHeaders headers_gen(cct, &new_env, &new_info);

  //  "GET", new_url=ip:port/, new_resource=bk/obj/ , RGW_SYS_PARAM_PREFIX * 3 + versionId
  headers_gen.init(method, new_url, new_resource, params);    

  headers_gen.set_http_attrs(extra_headers);

  if (key) {
    int ret = headers_gen.sign(*key);
    if (ret < 0) {
      ldout(cct, 0) << "ERROR: failed to sign request" << dendl;
      return ret;
    }
  }

  for (const auto& kv: new_env.get_map()) {
    headers.emplace_back(kv);   // http_date, auth
  }

  method = new_info.method;
  url = headers_gen.get_url();    // ip:port/bk/obj?a=b&c=d&e=f&versionId=g

  return 0;
}

//  "GET", ip:port/, bk/obj , RGW_SYS_PARAM_PREFIX * 3 + versionId
void RGWRESTGenerateHTTPHeaders::init(const string& _method, const string& _url, const string& resource, const param_vec_t& params)
{
  string params_str;
  map<string, string>& args = new_info->args.get_params();
  do_get_params_str(params, args, params_str);

  /* merge params with extra args so that we can sign correctly */
  for (auto iter = params.begin(); iter != params.end(); ++iter) {
    new_info->args.append(iter->first, iter->second);
  }

  url = _url + resource + params_str;   // ip:port/bk/obj?a=b&c=d&e=f&versionId=g

  string date_str;
  get_gmt_date_str(date_str);

  new_env->set("HTTP_DATE", date_str.c_str());

  method = _method;
  new_info->method = method.c_str();

  new_info->script_uri = "/";
  new_info->script_uri.append(resource);
  new_info->request_uri = new_info->script_uri;   // /bk/obj
}

void RGWRESTGenerateHTTPHeaders::set_extra_headers(const map<string, string>& extra_headers)
{
  for (auto iter : extra_headers) {
    const string& name = lowercase_dash_http_attr(iter.first);
    new_env->set(name, iter.second.c_str());
    if (is_x_amz(name)) {
      new_info->x_meta_map[name] = iter.second;
    }
  }
}

// 
bool rgw_create_s3_canonical_header(const req_info& info,
                                    utime_t* const header_time,   // NULL
                                    std::string& dest,
                                    const bool qsr)     // false 
{
  const char* const content_md5 = info.env->get("HTTP_CONTENT_MD5");
  if (content_md5) {
    for (const char *p = content_md5; *p; p++) {
      if (!is_base64_for_content_md5(*p)) {
        dout(0) << "NOTICE: bad content-md5 provided (not base64),"
                << " aborting request p=" << *p << " " << (int)*p << dendl;
        return false;
      }
    }
  }

  const char *content_type = info.env->get("CONTENT_TYPE");

  std::string date;
  meta_map_t qs_map;

  if (qsr) {
    get_v2_qs_map(info, qs_map); // handle qs metadata
    date = info.args.get("Expires");
  } else {
    const char *str = info.env->get("HTTP_X_AMZ_DATE");
    const char *req_date = str;
    if (str == NULL) {
      req_date = info.env->get("HTTP_DATE");
      if (!req_date) {
        dout(0) << "NOTICE: missing date for auth header" << dendl;
        return false;
      }
      date = req_date;
    }

    if (header_time) {
      struct tm t;
      if (!parse_rfc2616(req_date, &t)) {
        dout(0) << "NOTICE: failed to parse date for auth header" << dendl;
        return false;
      }
      if (t.tm_year < 70) {
        dout(0) << "NOTICE: bad date (predates epoch): " << req_date << dendl;
        return false;
      }
      *header_time = utime_t(internal_timegm(&t), 0);
    }
  }

  const auto& meta_map = info.x_meta_map;
  const auto& sub_resources = info.args.get_sub_resources();

  std::string request_uri;
  if (info.effective_uri.empty()) {
    request_uri = info.request_uri;
  } else {
    request_uri = info.effective_uri;
  }

  // GET, NULL, NULL, date, meta_map(自定义元数据), NULL, /bk/obj, sub_resources[versionId], dest
  rgw_create_s3_canonical_header(info.method, content_md5, content_type,
                                 date.c_str(), meta_map, qs_map,
				 request_uri.c_str(), sub_resources, dest);
  return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值