zer02
zer02

Reputation: 4011

C++ POST request with cURL + JSON Lib

I would like to do a POST request using cURL. I am using this (github:nlohmann/json) library to handle my JSON object creation. I receive the HTTP 200 Response, but the POST data is not being appended.

When calling std::cout<< json_data.dump() << std::endl; I receive a well-formed JSON.

{
    "a": [
        {
            "c": "0",
            "d": "0",
            "e": "0",
            "f": "0",
            "g": "1506961983",
            "h": "1506961986",
            "i": "3"
        },
        {
            "c": "1",
            "d": "2",
            "e": "1",
            "f": "1",
            "g": "1506961987",
            "h": "1506961991",
            "i": "4"
        }
    ],
    "b": "test"
}

I use this to append my data.

   struct curl_slist *headers=NULL; 
   headers = curl_slist_append(headers, "Accept: application/json");  
   headers = curl_slist_append(headers, "Content-Type: application/json");
   headers = curl_slist_append(headers, "charset: utf-8"); 
   curl_easy_setopt(curl, CURLOPT_POSTFIELDS,json_data.dump().c_str());

Documentation curl_easy_setopt documentation

If I look into my AWS logs. It says:

{
  "format": "json",
  "payload": 5,
  "qos": 0,
  "timestamp": 1506961394810,
  "topic": "test_topic"
}

Why is it showing the value of 5 instead of my JSON object?

Thanks for help, if anyone knows why.

Upvotes: 2

Views: 6440

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595319

On this line:

curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data.dump().c_str());

The string object returned by dump() is temporary and destroyed when curl_easy_setopt() exits, thus leaving CURLOPT_POSTFIELDS with a dangling pointer that may or may not still be pointing to the JSON data in memory by the time libCURL tries to post it.

Per the CURLOPT_POSTFIELDS documentation:

The data pointed to is NOT copied by the library: as a consequence, it must be preserved by the calling application until the associated transfer finishes. This behaviour can be changed (so libcurl does copy the data) by setting the CURLOPT_COPYPOSTFIELDS option.

So, you need to either:

  • change CURLOPT_POSTFIELDS to CURLOPT_COPYPOSTFIELDS:

    curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, json_data.dump().c_str());
    
  • save the result of json_data.dump() to a local variable that does not go out of scope until after curl_easy_perform() exits:

    std::string json = json_data.dump();
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
    ...
    

Upvotes: 8

Related Questions