C++开发示例
所有文档

          云数据库 TableStorage

          C++开发示例

          我们在写下边的示例代码时,为了简单清楚,便于理解,忽略了一些错误处理,用户基于以下示例开发的时候,可以自行补齐。

          生成认证字符串

          在访问云数据库 TableStorage 时,每个访问都需要使用用户的AK/SK生成认证字符串来进行身份认证,参考百度智能云鉴权认证机制百度智能云认证字符串生成代码示例

          // 我们在这里定义了一个HttpRequest结构体,在后续的demo中我们会使用到此结构体
          struct HttpRequest {
              HttpRequest() {
                  // 只支持ContentType为json
                  headers["Content-Type"] = "application/json";
              }
              std::string method;
              std::string path;
              std::map<std::string, std::string> headers;
              std::map<std::string, std::string> params;
              std::string body;
          };

          生成认证字符串的c++函数定义如下。

          我们在这里定义了一个根据HttpRequest生成认证字符串的函数,实现见本页最下方的百度智能云认证字符串C++实现,其它语言的实现可参考百度智能云认证字符串生成代码示例

          std::string gen_authorization(const HttpRequest& request, int timestamp);

          创建Instance

          当用户开通云数据库 TableStorage 服务后,需要先创建一个instance。

          create instance demo
          void create_instance() {
              // 获取当前时间戳
              time_t timestamp = time(NULL);
              // 初始化HttpRequest
              HttpRequest http_request;
              // 方法为PUT表示创建资源
              http_request.method = "PUT";
              // 将创建名为ins_demo的instance
              http_request.path = "/v1/instance/ins_demo";
              // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
              http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
              http_request.headers["Host"] = "bts.bd.baidubce.com";
              http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
           
              // 使用curl发送请求
              CURL* curl = curl_easy_init();
              struct curl_slist* curl_headers = NULL;
              // 填充header
              for (auto const& item : http_request.headers) {
                  std::string header = item.first + ":" + item.second;
                  curl_headers = curl_slist_append(curl_headers, header.c_str());
              }
              // 拼接Url
              std::string url("http://bts.bd.baidubce.com");
              url.append(http_request.path);
              // 设置Url
              curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
              // 设置headers
              curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
              // 设置method
              curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
              // 发送请求
              curl_easy_perform(curl);
              // 解析http返回码
              long http_code = -1;
              curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
              // 清理curl
              curl_easy_cleanup(curl);
          }

          创建Table

          用户在创建好Instance后,就可以在Instance中创建表了,下边的示例是创建一张默认结构的表,如果用户对于表结构有特别需求,可参考API参考增加参数。

          void create_table() {
              // 获取当前时间戳
              time_t timestamp = time(NULL);
              // 初始化HttpRequest
              HttpRequest http_request;
              // 方法为PUT表示创建资源
              http_request.method = "PUT";
              // 将在ins_demo中创建名为table_demo的table
              http_request.path = "/v1/instance/ins_demo/table/table_demo";
              // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
              http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
              http_request.headers["Host"] = "bts.bd.baidubce.com";
              http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
           
              // 使用curl发送请求
              CURL* curl = curl_easy_init();
              struct curl_slist* curl_headers = NULL;
              // 填充header
              for (auto const& item : http_request.headers) {
                  std::string header = item.first + ":" + item.second;
                  curl_headers = curl_slist_append(curl_headers, header.c_str());
              }
              // 拼接Url
              std::string url("http://bts.bd.baidubce.com");
              url.append(http_request.path);
              // 设置Url
              curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
              // 设置headers
              curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
              // 设置method
              curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
              // 发送请求
              curl_easy_perform(curl);
              // 解析http返回码
              long http_code = -1;
              curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
              // 清理curl
              curl_easy_cleanup(curl);
          }

          向Table写入数据

          用户创建好Table后,就可以向Table写入数据。

          void insert() {
              // 获取当前时间戳
              time_t timestamp = time(NULL);
              // 初始化HttpRequest
              HttpRequest http_request;
              // 方法为PUT表示创建资源,即写入数据
              http_request.method = "PUT";
              // 将向ins_demo中的表table_demo中写入一行数据
              http_request.path = "/v1/instance/ins_demo/table/table_demo/row";
              // 拼接写入的数据,为json格式,并且数据要经过UrlEncode
              // 写入rowkey(主键)为"www.baidu.com/0"的两列数据:col1,值为"val1",col2,值为"val2"
              http_request.body =
                  "{"
                      "\"rowkey\":\"www.baidu.com%2F0\","
                      "\"cells\":["
                      "{"
                          "\"column\":\"col1\","
                          "\"value\":\"val1\""
                      "},"
                      "{"
                          "\"column\":\"col2\","
                          "\"value\":\"val2\""
                      "}"
                  "]}";
              // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
              http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
              http_request.headers["Host"] = "bts.bd.baidubce.com";
              http_request.headers["Content-Length"] = std::to_string(http_request.body.size());
              http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
           
              // 使用curl发送请求
              CURL* curl = curl_easy_init();
              struct curl_slist* curl_headers = NULL;
              // 填充header
              for (auto const& item : http_request.headers) {
                  std::string header = item.first + ":" + item.second;
                  curl_headers = curl_slist_append(curl_headers, header.c_str());
              }
              // 拼接Url
              std::string url("http://bts.bd.baidubce.com");
              url.append(http_request.path);
              // 设置Url
              curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
              // 设置headers
              curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
              // 设置method
              curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
              // 设置body
              curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_request.body.c_str());
              // 发送请求
              curl_easy_perform(curl);
              // 解析http返回码
              long http_code = -1;
              curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
              // 清理curl
              curl_easy_cleanup(curl);
          }

          从Table读取数据

          一般来说,读取数据时,用户需要解析所读取的内容,所以我们在读示例里增加了curl获取返回内容的代码。用户可以指定rowkey从Table中读取数据。

          // curl回调方法,用于读出返回的content,即body内容
          size_t content_data(void* buffer, size_t size, size_t nmemb, void* userp) {
              *((std::string*)userp) = *((std::string*)userp) +
                                      std::string((const char*)buffer, size * nmemb);
              return size * nmemb;
          }
          // curl回调方法,用于读出返回的header
          size_t header_data(void* buffer, size_t size, size_t nmemb, void* userp) {
              *((std::string*)userp) = *((std::string*)userp) +
                                      std::string((const char*)buffer, size * nmemb);
              return size * nmemb;
          }
           
          void query() {
              // 获取当前时间戳
              time_t timestamp = time(NULL);
              // 初始化HttpRequest
              HttpRequest http_request;
              // 方法为GET表示获取资源
              http_request.method = "GET";
              // 将向ins_demo中的table_demo读取一条数据
              http_request.path = "/v1/instance/ins_demo/table/table_demo/row";
              // 拼接单条读请求,为json格式,并且数据要经过UrlEncode
              // 读取rowkey(主键)为"www.baidu.com/0"的两列数据:col1和col2
              // 如果需要读整行数据,则只需要设置rowkey即可
              http_request.body =
                  "{"
                      "\"rowkey\":\"www.baidu.com%2F0\","
                      "\"cells\":["
                      "{"
                          "\"column\":\"col1\""
                      "},"
                      "{"
                          "\"column\":\"col2\""
                      "}"
                  "]}";
              // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
              http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
              http_request.headers["Host"] = "bts.bd.baidubce.com";
              http_request.headers["Content-Length"] = std::to_string(http_request.body.size());
              http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
           
              // 使用curl发送请求
              CURL* curl = curl_easy_init();
              struct curl_slist* curl_headers = NULL;
              // 填充header
              for (auto const& item : http_request.headers) {
                  std::string header = item.first + ":" + item.second;
                  curl_headers = curl_slist_append(curl_headers, header.c_str());
              }
              // 拼接Url
              std::string url("http://bts.bd.baidubce.com");
              url.append(http_request.path);
              // 设置Url
              curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
              // 设置headers
              curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
              // 设置method
              curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
              // 设置body
              curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_request.body.c_str());
              // 设置返回的header,content
              // 如果你不需要解析header和content,则不需要做此设置,返回的content也会直接打印到标准输出
              std::string header;
              std::string content;
              curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, content_data);
              curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_data);
              curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);
              curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header);
              // 发送请求
              curl_easy_perform(curl);
              // 解析http返回码
              long http_code = -1;
              curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
              // 清理curl
              curl_easy_cleanup(curl);
              // 打印返回的header内容
              printf("query response header: %s.\n", header.c_str());
              // 打印返回的content内容,为json格式,具体可参考api文档
              // 如果你需要对返回的内容做下一步处理,可以将此content按json格式解析后作为后续使用
              printf("query result: %s.\n", content.c_str());
          }

          用户可以范围扫描数据。

          // curl回调方法,用于读出返回的content,即body内容
          size_t content_data(void* buffer, size_t size, size_t nmemb, void* userp) {
              *((std::string*)userp) = *((std::string*)userp) +
                                      std::string((const char*)buffer, size * nmemb);
              return size * nmemb;
          }
          // curl回调方法,用于读出返回的header
          size_t header_data(void* buffer, size_t size, size_t nmemb, void* userp) {
              *((std::string*)userp) = *((std::string*)userp) +
                                      std::string((const char*)buffer, size * nmemb);
              return size * nmemb;
          }
           
          void scan() {
              // 获取当前时间戳
              time_t timestamp = time(NULL);
              // 初始化HttpRequest
              HttpRequest http_request;
              // 方法为GET表示获取资源
              http_request.method = "GET";
              // 将向ins_demo中的table_demo读取数据
              http_request.path = "/v1/instance/ins_demo/table/table_demo/rows";
              // 拼接范围读请求,为json格式,并且数据要经过UrlEncode
              // 读取rowkey(主键)范围为[www.baidu.com/0, www.baidu.com/9)数据,并且读取其中两列:col1和col2
              // 注意includeStart和includeStop为区间的开闭,本示例中,区间为前闭后开
              // limit为1表示只返回第一行这个区间内的数据
              // rowkey区间和其它参数,用户可以参考api文档,按需配置
              http_request.body =
                  "{"
                      "\"startRowkey\":\"www.baidu.com%2F0\","
                      "\"includeStart\":true,"
                      "\"stopRowkey\":\"www.baidu.com%2F9\","
                      "\"includeStop\":false,"
                      "\"selector\":["
                      "{"
                          "\"column\":\"col1\""
                      "},"
                      "{"
                          "\"column\":\"col2\""
                      "}],"
                      "\"limit\":1"
                  "}";
              // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
              http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
              http_request.headers["Host"] = "bts.bd.baidubce.com";
              http_request.headers["Content-Length"] = std::to_string(http_request.body.size());
              http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
           
              // 使用curl发送请求
              CURL* curl = curl_easy_init();
              struct curl_slist* curl_headers = NULL;
              // 填充header
              for (auto const& item : http_request.headers) {
                  std::string header = item.first + ":" + item.second;
                  curl_headers = curl_slist_append(curl_headers, header.c_str());
              }
              // 拼接Url
              std::string url("http://bts.bd.baidubce.com");
              url.append(http_request.path);
              // 设置Url
              curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
              // 设置headers
              curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
              // 设置method
              curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
              // 设置body
              curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_request.body.c_str());
              // 设置返回的header,content
              // 如果你不需要解析header和content,则不需要做此设置,返回的content也会直接打印到标准输出
              std::string header;
              std::string content;
              curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, content_data);
              curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_data);
              curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);
              curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header);
              // 发送请求
              curl_easy_perform(curl);
              // 解析http返回码
              long http_code = -1;
              curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
              // 清理curl
              curl_easy_cleanup(curl);
              // 打印返回的header内容
              printf("query response header: %s.\n", header.c_str());
              // 打印返回的content内容,为json格式,具体可参考api文档
              // 如果你需要对返回的内容做下一步处理,可以将此content按json格式解析后作为后续使用
              printf("query result: %s.\n", content.c_str());
          }

          删除Table中数据

          用户也可以指定rowkey删除Table中的某行数据。

          void remove() {
              // 获取当前时间戳
              time_t timestamp = time(NULL);
              // 初始化HttpRequest
              HttpRequest http_request;
              // 方法为DELETE表示删除资源
              http_request.method = "DELETE";
              // 将删除ins_demo中的表table_demo中的一行数据
              http_request.path = "/v1/instance/ins_demo/table/table_demo/row";
              // 拼接写入的数据,为json格式,并且数据要经过UrlEncode
              // 删除rowkey(主键)为"www.baidu.com/0"的两列数据:col1,值为"val1",col2,值为"val2"
              // 如果要将整行,则不需要设置cells,只需设置rowkey即可
              http_request.body =
                  "{"
                      "\"rowkey\":\"www.baidu.com%2F0\","
                      "\"cells\":["
                      "{"
                          "\"column\":\"col1\","
                          "\"value\":\"val1\""
                      "},"
                      "{"
                          "\"column\":\"col2\","
                          "\"value\":\"val2\""
                      "}"
                  "]}";
              // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
              http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
              http_request.headers["Host"] = "bts.bd.baidubce.com";
              http_request.headers["Content-Length"] = std::to_string(http_request.body.size());
              http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
           
              // 使用curl发送请求
              CURL* curl = curl_easy_init();
              struct curl_slist* curl_headers = NULL;
              // 填充header
              for (auto const& item : http_request.headers) {
                  std::string header = item.first + ":" + item.second;
                  curl_headers = curl_slist_append(curl_headers, header.c_str());
              }
              // 拼接Url
              std::string url("http://bts.bd.baidubce.com");
              url.append(http_request.path);
              // 设置Url
              curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
              // 设置headers
              curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
              // 设置method
              curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
              // 设置body
              curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_request.body.c_str());
              // 发送请求
              curl_easy_perform(curl);
              // 解析http返回码
              long http_code = -1;
              curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
              // 清理curl
              curl_easy_cleanup(curl);
          }

          删除Table

          用户如果不再使用某张表,则可将其删除,其中的数据也会清理。

          void drop_table() {
              // 获取当前时间戳
              time_t timestamp = time(NULL);
              // 初始化HttpRequest
              HttpRequest http_request;
              // 方法为DELETE表示删除资源
              http_request.method = "DELETE";
              // 将删除ins_demo中名为table_demo的table
              http_request.path = "/v1/instance/ins_demo/table/table_demo";
              // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
              http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
              http_request.headers["Host"] = "bts.bd.baidubce.com";
              http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
           
              // 使用curl发送请求
              CURL* curl = curl_easy_init();
              struct curl_slist* curl_headers = NULL;
              // 填充header
              for (auto const& item : http_request.headers) {
                  std::string header = item.first + ":" + item.second;
                  curl_headers = curl_slist_append(curl_headers, header.c_str());
              }
              // 拼接Url
              std::string url("http://bts.bd.baidubce.com");
              url.append(http_request.path);
              // 设置Url
              curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
              // 设置headers
              curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
              // 设置method
              curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
              // 发送请求
              curl_easy_perform(curl);
              // 解析http返回码
              long http_code = -1;
              curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
              // 清理curl
              curl_easy_cleanup(curl);
          }

          删除Instance

          当用户不再使用某个Instance时,可将其删除,但需要注意的是,被删除的Instance必需是空的,即其中没有表存在,否则会拒绝删除操作。

          void drop_instance() {
              // 获取当前时间戳
              time_t timestamp = time(NULL);
              // 初始化HttpRequest
              HttpRequest http_request;
              // 方法为DELETE表示删除资源
              http_request.method = "DELETE";
              // 将删除名为ins_demo的instance
              http_request.path = "/v1/instance/ins_demo";
              // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
              http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
              http_request.headers["Host"] = "bts.bd.baidubce.com";
              http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
           
              // 使用curl发送请求
              CURL* curl = curl_easy_init();
              struct curl_slist* curl_headers = NULL;
              // 填充header
              for (auto const& item : http_request.headers) {
                  std::string header = item.first + ":" + item.second;
                  curl_headers = curl_slist_append(curl_headers, header.c_str());
              }
              // 拼接Url
              std::string url("http://bts.bd.baidubce.com");
              url.append(http_request.path);
              // 设置Url
              curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
              // 设置headers
              curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
              // 设置method
              curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
              // 发送请求
              curl_easy_perform(curl);
              // 解析http返回码
              long http_code = -1;
              curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
              // 清理curl
              curl_easy_cleanup(curl);
          }

          百度智能云认证字符串C++实现

          // 时间戳转为公有云utc时间串的函数
          // 例如:1535904000 转换为 2018-09-02T16:00:00Z
          inline std::string timestamp_to_utc(time_t timestamp) {
              struct tm* timeinfo = gmtime(&timestamp);
              const int buf_size = 32;
              char buf[buf_size];
              strftime(buf, buf_size, "%FT%TZ", timeinfo);
              return std::string(buf);
          }
          // UrlEncode实现,except_slash参数表示是否编码'/'
          inline std::string uri_encode(const std::string& src, bool except_slash = false) {
              static const char* hex = "0123456789ABCDEF";
              std::string dst = "";
              for (size_t i = 0; i < src.length(); i++) {
                  char c = src[i];
                  if (isalnum(c) || strchr("-_.~", c)) {
                      dst += c;
                  } else if (except_slash && c == '/') {
                      dst += c;
                  } else {
                      dst += '%';
                      dst += hex[(unsigned char)c >> 4];
                      dst += hex[(unsigned char)c & 0xf];
                  }
              }
              return dst;
          }
          // UriEncodeExceptSlash实现
          inline std::string uri_encode_except_slash(const std::string& str) {
              return uri_encode(str, true);
          }
          // 百度智能云认证字符串生成的C++实现
          // 其中有一些加密函数由于有公开库,我们这里直接调用,用户可找相应的公开库(如openssl)
          // 用户可以参考百度智能云生成认证字符串流程来阅读以下实现代码
          std::string gen_authorization(const HttpRequest& request, time_t timestamp) {
              // 1. 生成CanonicalRequest
              std::string http_method = request.method;
              // 1.1 生成CanonicalURI,
              std::string canonical_uri = uri_encode_except_slash(request.path);
              // 1.2 计算CanonicalQueryString
              std::string canonical_query = "";
              // 使用set结构暂存在后续遍历时可以保证天然字典序遍历,如果使用vector暂存需要配合sort按字典序排序
              std::set<std::string> encoded_params;
              // 对params遍历一次对kv做urlencode
              auto params_it = request.params.begin();
              for (; params_it != request.params.end(); ++params_it) {
                  if (params_it->first == "authorization" || params_it->first == "Authorization") {
                      continue;
                  }
                  std::string key = uri_encode(params_it->first);
                  std::string value = uri_encode(params_it->second);
                  encoded_params.insert(key + '=' + value); // 兼容value为空字符串的情形
              }
              // 对params遍历urlencode后的集合,拼接字符串
              auto enc_params_it = encoded_params.begin();
              for (; enc_params_it != encoded_params.end(); ++enc_params_it) {
                  if (enc_params_it != encoded_params.begin()) {
                      canonical_query += '&';
                  }
                  canonical_query += *enc_params_it;
              }
              // 1.3 计算CanonicalHeaders
              std::string canonical_header = "";
              // 使用set结构暂存在后续遍历时可以保证天然字典序遍历,如果使用vector暂存需要配合sort按字典序排序
              std::set<std::string> encoded_headers;
              // 对headers遍历一次,对key做转换小写、urlencoded操作,对value做去首尾空格、urlencoded操作
              auto headers_it = request.headers.begin();
              for (; headers_it != request.headers.end(); ++headers_it) {
                  // 将key部分转换为全小写
                  std::string key = headers_it->first;
                  for (size_t i = 0; i < key.length(); ++i) {
                      key[i] = ::tolower(key[i]);
                  }
                  // 将value部分去掉首尾的空白符
                  const char* blank_chars = " \n\r\t\v";
                  std::string value = headers_it->second;
                  value.erase(0, value.find_first_not_of(blank_chars));
                  value.erase(value.find_last_not_of(blank_chars) + 1);
                  if (value.empty()) {
                      continue;
                  }
                  std::string encoded_key = uri_encode(key);
                  std::string encoded_value = uri_encode(value);
                  encoded_headers.insert(encoded_key + ':' + encoded_value);
              }
              // 对headers遍历urlencode后的集合,拼接字符串
              auto enc_headers_it = encoded_headers.begin();
              for (; enc_headers_it != encoded_headers.end(); ++enc_headers_it) {
                  if (enc_headers_it != encoded_headers.begin()) {
                      canonical_header += '\n';
                  }
                  canonical_header += *enc_headers_it;
              }
              // 拼接生成CanonicalRequest
              std::string canonical_request = http_method + '\n'
                                            + canonical_uri + '\n'
                                            + canonical_query + '\n'
                                            + canonical_header;
              // 2. 生成SigningKey,这里我们直接调用了hmac_sha256函数,用户可以使用任意公开库中的HMAC-SHA256-HEX函数代替
              // 注意使用hmac_sha256函数时参数的顺序
              // 在生成鉴权串时的时间戳一定要和发送请求中Header域中的Date/x-bce-date相同
              // 用户的ak/sk
              const std::string ak = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
              const std::string sk = "ssssssssssssssssssssssssssssssss";
              // 拼接认证字符串前缀 : bce-auth-v1/{accessKeyId}/{timestamp}/{expirationPeriodInSeconds}
              std::string auth_string_prefix = "bce-auth-v1/";
              auth_string_prefix.append(ak + '/');
              auth_string_prefix.append(timestamp_to_utc(timestamp));
              // 认证字符串的超时时间(有效期)为1800秒,用户可以自行设置,时间长意味着效率高,但安全性会降低
              auth_string_prefix.append("/1800");
              std::string sign_key = hmac_sha256(auth_string_prefix, sk);
              // 3. 生成Signature
              std::string sign = hmac_sha256(canonical_request, sign_key);
              // 4. 生成认证字符串,即做拼接
              // 将前缀和Signature拼接得到完整的认证字符串
              // 与签名结果之间为两个”/”,含义是使用默认签名方式,signedHeaders内容留空
              std::string auth = auth_string_prefix + "//" + sign;
              return auth;
          }
          上一篇
          操作指南
          下一篇
          API参考