'curl PUT JSON body having issues processing array's

I'm developing a library that communicates with a REST API. The method I wrote for PUT calls has worked up until this point.

void Command::put(const std::string url, const std::string body)
{

  CURLcode ret;
  struct curl_slist *slist1;
  slist1 = NULL;
  // slist1 = curl_slist_append(slist1, "Content-Type: multipart/form-data;");
  slist1 = curl_slist_append(slist1, "Content-Type: application/json;");

  curl = curl_easy_init();
  if(curl)
  {
    curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 102400L);
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)12);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.79.1");
    curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
    curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS, "/Users/$USER/.ssh/known_hosts");
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
    curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, 1L);
    curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);

    ret = curl_easy_perform(curl);

    curl_easy_cleanup(curl);
    curl = NULL;
    curl_slist_free_all(slist1);
    slist1 = NULL;
  }
  curl_easy_cleanup(curl);
  curl = nullptr;
  curl_slist_free_all(slist1);
  slist1 = NULL;
}

However, it seems to not work with arrays. Below are three debug put calls and their output. The first two work. The third does not.

  // *** DEBUG ***
  commandWrapper->put(
    "http://192.168.1.7/api/x1CAh16Nr8NcKwgkUMVbyZX3YKFQrEaMAj5pFz0Z/lights/6/state", "{\"on\":true}");

  commandWrapper->put(
    "http://192.168.1.7/api/x1CAh16Nr8NcKwgkUMVbyZX3YKFQrEaMAj5pFz0Z/lights/6/state", "{\"bri\":123}");

  commandWrapper->put(
    "http://192.168.1.7/api/x1CAh16Nr8NcKwgkUMVbyZX3YKFQrEaMAj5pFz0Z/lights/6/state", "{\"xy\":[0.04,0.98]}");

[{"success":{"/lights/6/state/on":true}}]
[{"success":{"/lights/6/state/bri":123}}]
[{"error":{"type":2,"address":"/lights/6/state","description":"body contains invalid json"}}]2022-04-02T02:56:47.220Z - Living Room 1 - Status: 0

I'm a little lost on how to proceed. I verified that this command does work on the command line.



Solution 1:[1]

You need to change this line:

curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)12);

To this instead:

curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)body.size());

Or, simply omit CURLOPT_POSTFIELDSIZE_LARGE completely, since body.c_str() is a pointer to a null-terminated string in this situation. Curl can determinant the size for you.

The JSON {xy:[0.04,0.98]} is 16 characters, longer than the 12 characters you are claiming, so you are truncating the JSON during transmission, which is why the server thinks it is invalid. Both {"on":true} and {"bri":123} are 11 characters (12 if you count the null terminator), so they are not truncated.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1