I am trying to run a simple example using libcurl, but just running this simple example gives me CURLE_WRITE_ERROR when I execute the curl_easy_perform(...) command. Does anyone have any idea what I am doing wrong? I have also tried other sites besides example.com.
CURL *curl = curl_easy_init();
if(curl)
{
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/");
res = curl_easy_perform(curl); // returns CURLE_WRITE_ERROR always!
curl_easy_cleanup(curl);
}
OK turns out Joachim is right. I did need a write callback
size_t CurlWriteCallback(char* buf, size_t size, size_t nmemb, void* up)
{
TRACE("CURL - Response received:\n%s", buf);
TRACE("CURL - Response handled %d bytes:\n%s", size*nmemb);
// tell curl how many bytes we handled
return size*nmemb;
}
// ...
CURL *curl = curl_easy_init();
if(curl)
{
CURLcode res;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &CurlWriteCallback);
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
Related
This question already has answers here:
Save cURL content result into a string in C++
(7 answers)
Closed 1 year ago.
Here is my code:
CURL *curl;
CURLcode res;
curl = curl_easy_init();
std::string json_message = "{\r\n \"email\":\"test#abv.bg\",\r\n \"password\":\"asdasdasd\"\r\n}";
if(curl) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "https://www.examle.com/myUrl");
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Authorization: Bearer secretkeyHere");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
const char *data = json_message.c_str();
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
The problem is that when I execute that code the response of the http request is printed directly into my console application. I would like to store the response in a string without printing it into the console without intention.
Do you see why it is printed unintentionally and how can I store the response in a string?
By default, curl writes the received data to stdout. You can change that by using curl_easy_setopt() to specify a custom CURLOPT_WRITEFUNCTION callback, giving it a string* pointer via CURLOPT_WRITEDATA. For example:
static size_t writeToString(void *data, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
std::string *str = static_cast<std::string*>(userp);
str->append(static_cast<char*>(data), realsize);
return realsize;
}
...
CURL *curl = curl_easy_init();
if (curl) {
...
std::string respStr;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeToString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &respStr);
CURLcode res = curl_easy_perform(curl);
// use respStr as needed...
curl_easy_cleanup(curl);
}
Quite new to c++ and all of this so sorry for any awful awful mistakes that I may make.
I have a post function that I use to send data to a website and then returns other data to me.
The problem is that it times out at curl_easy_perform
Here's my source.
It was working not too long ago but it stopped for some weird reason. I can assure you that it is not the website as I've tried with many others.
size_t WriteCallback(char *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
string post(string source) {
CURL *curl;
CURLcode res;
string readBuffer;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "mywebsite");
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, source.length());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, source.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
cout << res << endl;
curl_easy_cleanup(curl);
return readBuffer;
}
curl_global_cleanup();
return 0;
}
Solved. Turns out something was wrong with how I initialized my console and main functions which I don't quite understand. Thanks anyways!
I'm trying to make an http post with libcurl library to create an InfluxDB database, as indicated in their website:
curl -i -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE mydb"
It looks like my code is not working. It doesnt give me any errors but db is not created. But instead if i try to add some points to an existing database, with the same function, it works. I think i miss the correct way of adding "q=CREATE DATABASE mydb" part. How should i change my code?
int main(int argc, char *argv[]){
char *url = "http://localhost:8086/query";
char *data = "q=CREATE DATABASE mydb";
/* should i change data string to json?
data = "{\"q\":\"CREATE DATABASE mydb\" }" */
bool res = createInfluxDB(url, data);
/*control result*/
return(0);
}
bool createInfluxDB(char *url, char *data) {
CURL *curl;
curl = curl_easy_init();
if(curl) {
CURLcode res;
/* What Content-type should i use?*/
struct curl_slist* headers = curl_slist_append(headers, "Content-Type: application/json");
/*--data-urlencode*/
char *urlencoded = curl_easy_escape(curl, data, int(strlen(data)));
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, urlencoded);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(urlencoded));
res = curl_easy_perform(curl);
/*omitted controls*/
curl_free(urlencoded);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return(true);
}
After analyzing packets with http post request (which was returning Bad Request) i arrived to the point that i shouldn't add query parameters as data. But instead it should be part of url. So after changing code like that, it works!
int main(int argc, char *argv[]){
char *url = "http://localhost:8086/query?q=CREATE+DATABASE+mydb";
bool res = createInfluxDB(url);
/*control result*/
return(0);
}
bool createInfluxDB(char *url) {
CURL *curl;
curl = curl_easy_init();
if(curl) {
CURLcode res;
struct curl_slist* headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
/*omitted controls*/
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return(true);
}
EDITED ANSWER:
You still got a missnamed var in a if statment:
if (urlencode) free(...
That should be
if (urlencoded) free(...
Then in your headers you set the application type as json and I don't think that's what you want.
Something like "application/x-www-form-urlencoded" may be better.
struct curl_slist* headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
ORIGNIAL ANSWER:
A workaround could be in your
char *data = curl_easy_escape(curl, json, int(strlen(json)));
That overload data with a json var that doesn't exist ?
Something like this may work better:
data = curl_easy_escape(curl, data, int(strlen(data)));
I'm trying to create a basic login program that's connected to server but when I try to save the response from a post request to a variable I wont get a response at all but if I don't try to save it I do get a response, I'm not really sure what I'm doing wrong, any help would be appreciated, cheers.
int post(string str1, string str2, string str3) {
string query = "user=" + str1 + "&pass=" + str2;
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://www.vlone.cc/pwned.php");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, query.c_str());
// when i comment out these 2 lines I get a response otherwise I don't
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_to_string);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &str3);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
Write to string
size_t write_to_string(void *ptr, size_t size, size_t count, void *stream) {
((string*)stream)->append((char*)ptr, 0, size*count);
return size*count;
}
I used Curl 7.2.9 and checked connection this way:
Here's example:
curl = curl_easy_init();
bool result = false;
if(curl)
{
curl_easy_setopt(curl, CURLOPT_URL, m_checkConnectionUrl);
CURLcode res = curl_easy_perform(curl);
}
if(res != CURLE_OK)
{
}
else
{
// connection is available
}
Now I switched to curl-7.33.0 and got *CURLE_WRITE_ERROR* error,
and to make it work I must code it like
std::string output;
char* encodedUrl = curl_easy_escape(curl, m_checkConnectionUrl, 0);
curl_easy_setopt(curl, CURLOPT_POST, 0);
curl_easy_setopt(curl, CURLOPT_URL, encodedUrl);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeMemoryCurlCallbackStub);
CURLcode res = curl_easy_perform(curl);
But I don't need to write anything. Any ideas?
Manily the Curl option *CURLOPT_WRITEFUNCTION* is used to have a certain amount of data periodically(at the callback functoin) to handle a large file download. I don't see any reason to use this with your curl purpose, regardless the version.
Remove the *CURLOPT_POST*(by default its 0) and *CURLOPT_WRITEFUNCTION* from the code and it should work. If it doesn't, then you are doing something wrong at other places in your code!
Also, if you are checking whether the URL is ok or not, then using CURL is ok. But to only check for connection, you can only check whether the port 80 of the domain is on or not.
You need to write a writecallback as well
size_t CurlWriteCallback(char* buf, size_t size, size_t nmemb, void* up)
{
TRACE("CURL - Response received:\n%s", buf);
TRACE("CURL - Response handled %d bytes:\n%s", size*nmemb);
// tell curl how many bytes we handled
return size*nmemb;
}
if(curl)
{
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &CurlWriteCallback);
curl_easy_setopt(curl, CURLOPT_URL, m_checkConnectionUrl);
CURLcode res = curl_easy_perform(curl);
}
Old question, but I have just encountered a similar problem. After some more googling this is the solution:
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
curl_easy_perform(curl);
// OK, now we are connected (if nothing bad happened),
// but it would be nice to communicate with the server:
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 0L);
//now we can do the actual communication
I used this to separate authentication from the actual emails sending.