c++ use curllib send REST API request to Web server
阅读原文时间:2023年07月11日阅读:1

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:

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 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();

}