0

What I want to do is to perform CURL request with parameters and values by using GET method but using JSON.

I'm trying to perform the following:

curl -X GET \
-H "X-Parse-Application-Id: 12345_Example" \
-H "X-Parse-REST-API-Key: abcde_Example" \
-G \
--data-urlencode "where={ \"pin\":\"A string\" }" \
https://urlExample/classes/Pins

as you can see the where URL parameter constraining the value for keys should be encoded JSON.

This is my code:

std::size_t callback(
    const char* in,
    std::size_t size,
    std::size_t num,
    char* out)
{
    std::string data(in, (std::size_t) size * num);
    *((std::stringstream*) out) << data;
    return size * num;
}

    public: Json::Value query(const char* serverAddress, const char* applicationId, const char* restAPIKey) {
        CURL* curl = curl_easy_init();
    
        curl_slist* headerlist = NULL;
        headerlist = curl_slist_append(headerlist, applicationId);
        headerlist = curl_slist_append(headerlist, restAPIKey);
    
        // Set HEADER.
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
    
        // Set remote URL.
        curl_easy_setopt(curl, CURLOPT_URL, serverAddress);
    
        // Don't bother trying IPv6, which would increase DNS resolution time.
        curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
    
        // Don't wait forever, time out after 10 seconds.
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
    
        // Follow HTTP redirects if necessary.
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    
        // Response information.
        int httpCode(0);
        std::stringstream httpData;
    
        // Hook up data handling function.
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
    
        // Hook up data container (will be passed as the last parameter to the
        // callback handling function).  Can be any pointer type, since it will
        // internally be passed as a void pointer.
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &httpData);
    
        // Run our HTTP GET command, capture the HTTP response code, and clean up.
        curl_easy_perform(curl);
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
        curl_easy_cleanup(curl);
    
        if (httpCode == 200) {
            // Response looks good - done using Curl now. Try to parse the results.
            Json::Value jsonData;
            Json::CharReaderBuilder jsonReader;
            std::string errs;
    
            if (Json::parseFromStream(jsonReader, httpData, &jsonData, &errs)) {
                return jsonData["results"];
            }
            else {
                std::cout << "Could not parse HTTP data as JSON" << std::endl;
                std::cout << "HTTP data was:\n" << httpData.str() << std::endl;
                return NULL;
            }
        }
        else {
            std::cout << "Couldn't GET from " << serverAddress << " - exiting" << std::endl;
            return NULL;
        }
    }

What should I include in my code in order to perform the GET method with encoded JSON?

According to the documentation of the Server API I'm using, when reading objects, this is what it says for curl: back4app API Reference

READING OBJECTS:

To retrieve an object, you'll need to send a GET request to its class endpoint with your app's credentials in the headers and the query parameters in the URL parameters. This task can be easily accomplished just by calling the appropriated method of your preferred Parse SDK. Please check how to do it in the right panel of this documentation.

Request URL https://parseapi.back4app.com/classes/Pins

Method GET

Headers X-Parse-Application-Id: BCrUQVkk80pCdeImSXoKXL5ZCtyyEZwbN7mAb11f

X-Parse-REST-API-Key: swrFFIXJlFudtF3HkZPtfybDFRTmS7sPwvGUzQ9w

Parameters A where URL parameter constraining the value for keys. It should be encoded JSON.

Success Response Status 200 OK

Headers content-type: application/json;

Body a JSON object that contains a results field with a JSON array that lists the objects.

EDIT:

Based on: Daniel Stenberg's answer I tried the following:

std::string temp = "where={ \"pin\":\"A string\" }";
char* encoded = curl_easy_escape(curl, temp.c_str(), temp.length());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, std::strlen(encoded));
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, encoded);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");

But no success. Should libcurl update their API and include such a feature for this case?

Simple
  • 730
  • 6
  • 16
  • (1) URL-encode the JSON string. (2) Concatenate the URL, the `?` character, and the output of step 1. (3) Use the output of step 2 as the URL. – cdhowie Aug 17 '20 at 04:00
  • @cdhowie I already thought in that solution, but I'm looking for something like `CURLOPT_POSTFIELDS` but for GET method instead. – Simple Aug 17 '20 at 04:23
  • As far as I know, this (`-G`) is not a libcurl feature, it's a curl command-line feature only. I don't think there is a curlopt for this. – cdhowie Aug 17 '20 at 18:00

1 Answers1

1

OK -- I am going to answer this one more time. This time correctly. I glossed over the fact that you posted the documentation in your question. Totally skipped it. No idea why my brain does that. Maybe it hates documentation and instinctively skips it.

So, the answer to your question is quite simple.

Keep your original code that's in your question (totally ignore the code that you posted in your Edit, it's totally wrong), but instead of doing this:

curl_easy_setopt(curl, CURLOPT_URL, serverAddress);

Do this:

const std::string whereQuery(curl_easy_escape(curl, "{ \"pin\":\"A string\" }", 0));
const std::string url("https://parseapi.back4app.com/classes/Pins?where=" + whereQuery);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

Sorry for dragging that out. I need to read questions better.

Andy
  • 10,110
  • 3
  • 28
  • 47
  • 1
    @Simple -- again, I apologize for dragging that out. If you have any more questions about it let me know. The rest of the APIs look like they are POSTing `application/json`. That you will *not* have to "url-encode" as it is part of the post data of the request. – Andy Aug 21 '20 at 03:31
  • I appreciate your apology and I accept it. Thanks again, now I'm aware of it, for `POST` and `PUT` they're using `Content-Type: application/json` in the `headers`, so I will not url-encode it. – Simple Aug 21 '20 at 03:50