C++ Signing Guide
Preparing the Environment
This section uses Linux Ubuntu as an example. Before calling APIs, install the required SSL tools.
- Install the OpenSSL library.
apt-get install libssl-dev
- Install the curl library.
apt-get install libcurl4-openssl-dev
Obtaining the SDK
Log in to the APIG console and choose Help Center > SDK Process Flow. Then download the SDK.
Decompress the downloaded package to the current folder. The following table shows the directory structure.
| Name | Description |
|---|---|
| hasher.cpp | SDK code |
| hasher.h | |
| header.h | |
| RequestParams.cpp | |
| RequestParams.h | |
| signer.cpp | |
| signer.h | |
| constants.h | |
| Makefile | Makefile file |
| main.cpp | Sample code |
Request Signing and API Calling
After the calling information is modified, the sample code can be directly called. For details about the calling information, see Preparations.
- Add the following references to main.cpp:
1 2 3 4 5
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <curl/curl.h> #include "signer.h"
- Generate a new signer and enter the AK and SK.
- In this example, the AK and SK stored in the environment variables are used. Specify the environment variables CLOUD_SDK_AK and CLOUD_SDK_SK in the local environment first. The following uses Linux as an example to describe how to set the obtained AK/SK as environment variables.
- Open the terminal and run the following command to open the environment variable configuration file:
- Set environment variables, save the file, and exit the editor.
export CLOUD_SDK_AK="Obtained AK" export CLOUD_SDK_SK="Obtained SK"
- Run the following command to apply the modification:
- Generate a new signer and enter the configured environment variables.
1 2
//Set the AK/SK to sign and authenticate the request. Signer signer(getenv("CLOUD_SDK_AK"), getenv("CLOUD_SDK_SK"));
- In this example, the AK and SK stored in the environment variables are used. Specify the environment variables CLOUD_SDK_AK and CLOUD_SDK_SK in the local environment first. The following uses Linux as an example to describe how to set the obtained AK/SK as environment variables.
- Generate a new RequestParams request, and specify the method, domain name, request URI, query strings, and request body.
1 2 3 4 5 6
//Specify a request method, such as GET, PUT, POST, DELETE, HEAD, and PATCH. //Set a request URL. //Set parameters for the request URL. //Add a body if you have specified the PUT or POST method. Special characters, such as the double quotation mark ("), contained in the body must be escaped. RequestParams* request = new RequestParams("GET", "service.region.example.com", "/v1/{project_id}/vpcs", "limit=2", "");
- Add other headers required for request signing or other purposes. For example, add the X-Project-Id header in multi-project scenarios or the X-Domain-Id header for a global service.
1 2
//Add header parameters, for example, X-Domain-Id for invoking a global service and X-Project-Id for invoking a project-level service. request->addHeader("X-Project-Id", "xxx");
- Execute the following function to add the generated headers as request variables.
1signer.createSignature(request);
- Use the curl library to access the API and view the access result.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct MemoryStruct *mem = (struct MemoryStruct *)userp; mem->memory = (char*)realloc(mem->memory, mem->size + realsize + 1); if (mem->memory == NULL) { /* out of memory! */ printf("not enough memory (realloc returned NULL)\n"); return 0; } memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize; } //send http request using curl library int perform_request(RequestParams* request) { CURL *curl; CURLcode res; struct MemoryStruct resp_header; resp_header.memory = (char*)malloc(1); resp_header.size = 0; struct MemoryStruct resp_body; resp_body.memory = (char*)malloc(1); resp_body.size = 0; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, request->getMethod().c_str()); std::string url = "http://" + request->getHost() + request->getUri() + "?" + request->getQueryParams(); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); struct curl_slist *chunk = NULL; std::set<Header>::iterator it; for (auto header : *request->getHeaders()) { std::string headerEntry = header.getKey() + ": " + header.getValue(); printf("%s\n", headerEntry.c_str()); chunk = curl_slist_append(chunk, headerEntry.c_str()); } printf("-------------\n"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, request->getPayload().c_str()); curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void *)&resp_header); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&resp_body); //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } else { long status; curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &status); printf("status %d\n", status); printf(resp_header.memory); printf(resp_body.memory); } free(resp_header.memory); free(resp_body.memory); curl_easy_cleanup(curl); curl_global_cleanup(); return 0; }
- Run the make command to obtain a main executable file, execute the file, and then view the execution result.