CURLOPT_POSTFIELD value not recognized - c++

Thanks to #Mat 's comment i got the solution:
I replaced
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, cQuery);
with
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(cQuery));
curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, cQuery);
i am currently struggling at a more or less strange problem which drives me nuts.
I am using the following code to create the value i want to use for CURLOPT_POSTFIELDS to perform a CURL request.
string query;
map<string, string> parameters = resource->GetParameters();
typedef std::map<std::string, std::string>::iterator it_type;
int i = 0;
for (it_type iterator = parameters.begin(); iterator != parameters.end(); iterator++, i++) {
if (i > 0)
query.append("&");
query = query.append(iterator->first).append("=").append(iterator->second);
}
curl_easy_setopt(curl, CURLOPT_POST, true);
const char *cQuery = query.c_str();
cout << cQuery << endl;
cout << "grant_type=client_credentials&scope=default" << endl;
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, cQuery);
The output of both cout are:
grant_type=client_credentials&scope=default
grant_type=client_credentials&scope=default
If I am using the cQuery variable as the value, the server is responding that i didnt specify the grant type.
If I am replacing
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, cQuery);
with
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "grant_type=client_credentials&scope=default");
it works fine.
My background is more Java and C# related, so i am assuming i missunderstand some of the c++ basics. I am also a newbie on stackoverflow, so if i am doing sth. wrong please let me know.
I am looking forward to your answers. Thank you for your help.

Thanks to #Mat 's comment i got the solution:
I replaced
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, cQuery);
with
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(cQuery));
curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, cQuery);

Related

How would I go about extracting specific values from a curl request into arrays in c++

I have a variable "s" that stores the output of the curl request.
My code is as follows:
int main(void)
{
std::string s;
CURL* curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "www.ecobliss.co.za/run_student_query.php?query=Select%20*%20FROM%20data%20WHERE%20ID%20%3C%2030");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
std::cout << s << std::endl;
struct curl_slist* headers = NULL;
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
return 0;
}
The output of the request is as follows:
<p>Results from your query:</p><br>{"ID":"26","datetime":"2022-03-13 03:21:07","temperature":"25.3","humidity":"80.9","pressure":"1020.2"}<br>{"ID":"27","datetime":"2022-03-13 05:12:47","temperature":"24.8","humidity":"82.1","pressure":"1020.5"}<br>{"ID":"28","datetime":"2022-03-13 05:29:05","temperature":"24.9","humidity":"83.6","pressure":"1020.5"}<br>{"ID":"29","datetime":"2022-03-13 05:29:07","temperature":"24.9","humidity":"83.8","pressure":"1020.5"}
How would I go about putting the values of temperature, humidity and pressure into 3 different arrays?
You can split the task into the two pieces: 1) extract json parts by searching the delimiter, 2) parse each json with any open json lib. Personally I prefer the one included in Wt library but there are many.

Using CURL in function in c++

I'm trying tu use curl in c++ using function.
Example:
#define ...
...
...
/* CURL parameters */
CURL *curl = curl_easy_init();
CURLcode res;
string readBuffer;
void setHeader(){
if(curl) {
/* Headers */
struct curl_slist *chunk = NULL;
chunk = NULL;
chunk = curl_slist_append(chunk, "Connection:keep-alive");
..
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
}
}
void myFunction1(){
setHeader();
curl_easy_setopt(curl, CURLOPT_URL, "....");
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookiePath);
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookiePath);
res = curl_easy_perform(curl);
cout << readBuffer;
curl_easy_cleanup(curl);
}
void myFunction2(){
setHeader();
curl_easy_setopt(curl, CURLOPT_URL, "....");
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookiePath);
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookiePath);
res = curl_easy_perform(curl);
cout << readBuffer;
curl_easy_cleanup(curl);
}
In the main function i call myFunction1 or myFunction2;
I don't know if is right to use libcurl in this way, but I'm having a problem.
I use this to login in my site, so I save the cookie whit this code:
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookiePath);
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookiePath);
int main(){
curl_global_init(CURL_GLOBAL_ALL);
myFunction1();
myFunction2();
curl_global_cleanup();
}
Suppose i login and save the cookie in myFunction1.
When I'm trying to set in the myFunction2 it crash on the CURLOPT_COOKIEFILE row.
I don't know why the cookie is saved in the file, but it can't be used beacuse when I run the program it crash on that row.
Sorry for my English
Thank's
The reason of my problem is that when I use the curl_easy_cleanup(curl) and then curl_easy_init I change the sessionID, so the cookie that I've saved are no longer good. So I use at the first curl_easy_init, then I make all my request in my functions, and at the end of my program I use curl_easy_cleanup. To clean the CURL OPTION you can use: curl_easy_reset(). I've update this post for people that can have my same problem.

libcurl http post send data to server

curl_easy_setopt(curl, CURLOPT_URL, "127.0.0.1:8081/get.php");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS,"pulse=70 & temp=35" );
this above code run successfully but when I pass this
int pulsedata = 70;
int tempdata = 35;
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "pulse=pulsedata & temp = tempdata");
when I run this above line it give me error
how can I pass this pulsedata and tempdata ??
A possible C solution:
char sendbuffer[100];
snprintf(sendbuffer, sizeof(sendbuffer), "pulse=%d&temp=%d", pulsedate, tempdata);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, sendbuffer);
You can't use variable in strings like that, you have to format the string.
A possible C++ solution might be to use std::ostringstream like this:
std::ostringstream os;
os << "pulse=" << pulsedata << "&temp=" << tempdata;
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, os.str().c_sr());
With this solution, the std::ostringstream object (os in my example) needs to be alive until the CURL calls are all done.
Also note that the query-string I construct does not contain any spaces.

LibCurl CURLOPT_URL not accepting string? C++

So basically what I want to do is use libcurl to fetch slightly different urls, e.g.:
http://foo.com/foo.asp?name=*NAMEHERE*
What I would like to do is iterate through a vector of names and get each one, e.g.:
http://foo.com/foo.asp?name=James
Then
http://foo.com/foo.asp?name=Andrew
And so on.
However, when I try doing this:
int foo (){
CURL *curl;
CURLcode success;
char errbuf[CURL_ERROR_SIZE];
int m_timeout = 15;
if ((curl = curl_easy_init()) == NULL) {
perror("curl_easy_init");
return 1;
}
std::vector<std::string> names;
names.push_back("James");
names.push_back("Andrew");
for (std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i){
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, long(m_timeout));
curl_easy_setopt(curl, CURLOPT_URL, "http://foo.com/foo.asp?name=" + *i);
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookies.txt");
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookies.txt");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L);
}
if ((success = curl_easy_perform(curl)) != 0) {
fprintf(stderr, "%s: %s\n", "curl_easy_perform", errbuf);
return 1;
}
curl_easy_cleanup(curl);
return 0;
}
It gives me an error:
Cannot pass object of non-trivial type 'std::__1::basic_string<char>' through variadic function; call will abort at runtime
On this line:
curl_easy_setopt(curl, CURLOPT_URL, "http://foo.com/foo.asp?name=" + *i);
because of the + *i.
Is what I want to do possible? Is there a solution?
EDIT: Thanks for the answer, but for some reason, when I run this it only gets the website with the last string in the vector, and it ignores the other ones. In my case, it skips James and goes straight to Andrew. Why does that happen?
The parameter passed to curl_easy_setopt for CURLOPT_URL needs to be a char * instead of a std::string. You can get a const char * from a std::string by calling its c_str member function:
std::string url = "http://foo.com/foo.asp?name=" + *i;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
For anyone who ends up here in the future, take a look at the curl manual if you haven't already. There's also an online book.
The documentation for curl_easy_setopt says you need to read about a specific option to know what parameter type to use.
All options are set with an option followed by a parameter. That parameter can be a long, a function pointer, an object pointer or a curl_off_t, depending on what the specific option expects. Read this manual carefully as bad input values may cause libcurl to behave badly!
The documentation for CURLOPT_URL says exactly what the parameter type needs to be.
Pass in a pointer to the URL to work with. The parameter should be a char * to a zero terminated string which must be URL-encoded in the following format:
scheme://host:port/path
for some reason, when I run this it only gets the website with the last string in the vector, and it ignores the other ones. In my case, it skips James and goes straight to Andrew. Why does that happen?
You are looping through all of the names configuring the curl object with a different name on each loop iteration, THEN you are calling curl_easy_perform() only after the loop has finished, so it will retrieve only the last name that was configured. You need to move your call to curl_easy_perform() inside of the loop instead:
for (std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i)
{
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, long(m_timeout));
string url = "http://foo.com/foo.asp?name=" + *i;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookies.txt");
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookies.txt");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L);
success = curl_easy_perform(curl);
if (success != 0) {
fprintf(stderr, "%s: %s\n", "curl_easy_perform", errbuf);
// handle the error as needed...
continue;
}
// use the downloaded content as needed...
}

error when creating folder on dropbox via libcurl

I am trying to make a c++ application that uses Dropbox. When I am trying to create a new folder I take the following error: {"error": "Not Found"} and "HTTP/1.1 404 Not Found".
I have followed the instruction of Dropbox's REST Api, so I have used the POST method. (I am not sure if I can use PUT, instead).
Here is my code:
void createDirectory(const char *new_Directory_Path)
{
string create_Directory_Url = "https://api.dropbox.com/1/fileops/create_folder/sandbox/test_folder";
CURL* curl = curl_easy_init();
if(!curl)
{
CURLcode res;
struct curl_slist *headers = NULL;
string my_header = "Authorization: OAuth oauth_version=\"1.0\", oauth_signature_method=\"PLAINTEXT\",
oauth_consumer_key=\""
+ m_consumer_key + "\", oauth_token=\"" + m_accessKey + "\", oauth_signature=\""
+ m_consumer_secret + "&" + m_accessSecret + "\"";
headers = curl_slist_append(headers, my_header.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(curl, CURLOPT_URL, create_Directory_Url.c_str());
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
}
Please, does anyone have an idea about what am I doing wrong?
Looking at the documentation I belive you want to leave sandbox/test_folder off of the url and use root=sandbox & path=test_folder as form values.
Here is an example of submitting form parameters: http://curl.haxx.se/libcurl/c/postit2.html
EDIT:
I found another example, here: https://github.com/geersch/DropboxRESTApi/blob/master/src/part-3/README.md which seems to show the parameters being added to the url's query string rather than as form values. The doc page isn't clear. It just shows them as parameters but doesn't specify which kind.