E.g and explaination:
- Pre-condition: Server is running and can reciever CURL command with json format message, libcurl and jsoncpp lib installed and configured in makefile.
- Curl command line. use POST command to request data
- curl -X POST http://xx.xx.xx.xx:port/rest/xxx -H 'Content-Type: application/json' -H 'fieldname: value' -d'{"yyy" :{"fieldname1" :{"Value" : "999"},"fieldname2" :{"Value" : "777"}}'
C++ code to send request to get access token:
#define RESPONSE_BODY_SIZE 4096
int getData()
{
CURLcode res;
CURL * curl;
JSONCPP_STRING errs;
Json::Value root, res_output;
Json::CharReaderBuilder reader_builder;
bool json_res;
char response_body[RESPONSE_BODY_SIZE] = {'\0'};
memset(response_body, 0 , sizeof(response_body));
struct curl_slist *headers=NULL;
try
{
string auth_str = "Authorization: Basic " + _auth_header;
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
headers = curl_slist_append(headers, auth_str.c_str());
string URL = "http://xxxx/...;
curl = curl_easy_init();
if(curl == NULL)
{
curl_slist_free_all(headers);
return FAILURE;
}
if (//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1) != CURLE_OK ||
//curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug) != CURLE_OK ||
curl_easy_setopt(curl, CURLOPT_URL, URL.c_str()) != CURLE_OK ||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers) != CURLE_OK ||
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0)!= CURLE_OK ||
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0)!= CURLE_OK ||
curl_easy_setopt(curl, CURLOPT_NOBODY, 1) != CURLE_OK ||
curl_easy_setopt(curl, CURLOPT_POST, 1) != CURLE_OK ||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1) != CURLE_OK ||
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 180000) != CURLE_OK ||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData) != CURLE_OK ||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, response_body) != CURLE_OK )
{
GFRLOG_ERROR("Couldn't set cURL options");
if (curl)
{
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return -1;
}
else
{
GFRLOG_DEBUG("curl setopt done");
}
res = curl_easy_perform(curl);
if (CURLE_OK == res)
{
/* response E.g:
{
"access_token": "3776be6d-1394-40a3-bbbb-6e54c1ba8594",
"token_type": "bearer",
"expires_in": 43199,
"scope": "read write trust"
}*/
char *content_type;
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &content_type);
if((CURLE_OK == res) && content_type)
{
std::unique_ptr<Json::CharReader> const jsonReader(reader_builder.newCharReader());
json_res = jsonReader->parse(response_body, response_body + strlen(response_body), &root, &errs);
if (!json_res || !errs.empty()) {
GFRLOG_DEBUG("parse response Json err: " << errs);
if (curl)
{
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return FAILURE;
}
else
{
_access_token = root["access_token"].asString();
_expires_in = atoi(root["expires_in"].asString().c_str());
}
}
}
else{
GFRLOG_ERROR("Failed to get response from " << URL << " error msg: "<< curl_easy_strerror(res));
if (curl)
{
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return FAILURE;
}
}
catch(const Json::LogicError &e)
{
GFRLOG_ERROR("Parse json string error!");
if (curl)
{
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return FAILURE;
}
if (curl)
{
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return SUCCESS;
}
static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
{
if(itype == CURLINFO_TEXT)
{
printf("[TEXT]%s\n", pData);
}
else if(itype == CURLINFO_HEADER_IN)
{
printf("[HEADER_IN]%s\n", pData);
}
else if(itype == CURLINFO_HEADER_OUT)
{
printf("[HEADER_OUT]%s\n", pData);
}
else if(itype == CURLINFO_DATA_IN)
{
printf("[DATA_IN]%s\n", pData);
}
else if(itype == CURLINFO_DATA_OUT)
{
printf("[DATA_OUT]%s\n", pData);
}
return 0;
}
static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
char* response_body = (char*)lpVoid;
uint32_t response_body_len = strlen(response_body);
uint32_t len = size * nmemb;
if (len > RESPONSE_BODY_SIZE - response_body_len - 1)
{
len = RESPONSE_BODY_SIZE - response_body_len - 1;
}
memcpy(response_body + response_body_len, buffer, len);
return size*nmemb;
}
/* below functions should call at the beginnig or and in the end
Do not call it in each thread!*/
int curl_global_initiate()
{
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK )
{
GFRLOG_BYPASS("curl_global_init failed");
return FAILURE;
}
else{
GFRLOG_BYPASS("curl_global_init done");
return SUCCESS;
}
}
int curl_global_clean()
{
GFRLOG_BYPASS("curl_global_cleanup done");
curl_global_cleanup();
}