How to rewrite POST request from python to C++ with curl - c++

I have POST request on python with a lot of settings, and I don't uderstand how their look like in curl.
data_str = '{' + '"username": "{}", "domain_id": {}, "password": {}'.format(login, domain_id, password) + '}'
try:
data = requests.post("https://example.com/v/session",
proxies=proxy,
verify=False,
data=data_str,
headers={"Content-Type": "application/json;charset=UTF-8",
"Accept": "application/json"})
if is_json(data.text):
print(data)
I find that url set parament CURLOPT_URL, headers - CURLOPT_HTTPHEADER. But how set proxy, verify, data ? How get json as in python ?
how to complete the code that it have the same result as in python:
CURL *curl = curl_easy_init();
struct curl_slist *list = NULL;
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
list = curl_slist_append(list, "Shoesize: 10");
list = curl_slist_append(list, "Accept:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
curl_easy_perform(curl);
curl_slist_free_all(list); /* free the list again */
}

In order to get the return data from the curl request, we need a callback function for the CURLOPT_WRITEFUNCTION option.
The proxy, data, verify parameters should be set as following :
#include <iostream>
#include <string>
#include <curl/curl.h>
size_t curlWriter(void *contents, size_t size, size_t nmemb, std::string *s)
{
size_t newLength = size*nmemb;
try
{
s->append((char*)contents, newLength);
}
catch(std::bad_alloc &e)
{
//memory problem
return 0;
}
return newLength;
}
int main()
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl)
{
std::string strResponse;
std::string strPostData = "my data post";
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/v/session");
curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L);
//set the proxy
curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.net");
curl_easy_setopt(curl, CURLOPT_PROXYPORT, 8080L);
//verify=False. SSL checking disabled
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
//set the callback function
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriter);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &strResponse);
/* size of the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strPostData.length() );
/* pass in a pointer to the data - libcurl will not copy */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPostData.c_str() );
/* Execute the request */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
{
std::cerr << "CURL error : " << curl_easy_strerror(res) << std::endl;
}else {
std::cout << "CURL result : " << strResponse << std::endl;
}
curl_easy_cleanup(curl);
}
}

Related

Sending an email using curl c++

Im trying to send an email using curl c++, i managed to log in well and when i run the program it works fine, does not throw any error, but the email never comes.
This is my code:
#include <iostream>
#include <curl/curl.h>
static const char *payload_text =
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
"To: " "mailto" "\r\n"
"From: " "mymail" "\r\n"
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd#"
"rfcpedant.example.org>\r\n"
"Subject: SMTP example message\r\n"
"\r\n" /* empty line to divide headers from body, see RFC5322 */
"The body of the message starts here.\r\n"
"\r\n"
"It could be a lot of lines, could be MIME encoded, whatever.\r\n"
"Check RFC5322.\r\n";
size_t read_function(char *buffer, size_t size, size_t nmemb,char *data)
{
size_t len;
if(size == 0 or nmemb == 0)
{
return 0;
}
if(data)
{
len = strlen(data);
memcpy(buffer, data, len);
return len;
}
return 0;
}
int main()
{
CURL *curl;
CURLcode res = CURLE_OK;
const char *data = payload_text;
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_USERNAME, "mymail");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "password");
curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.gmail.com:587");
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, "my mail");
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, "mailto");
curl_easy_setopt(curl, CURLOPT_READDATA,payload_text);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_function);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
}
res = curl_easy_perform(curl);
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
return 0;
}
I think the problem is in the curl options READDATA and READUNCTION.
In the documentation says that you have to pass as an argument to READDATA a data pointer.
const char *data = payload_text; is the data pointer, right?
then READFUNCTION takes as an argument a function which return the size of the data and i think that is what size_t read_function(char *buffer, size_t size, size_t nmemb,char *data) is doing.
I am new in this so any advice would be good for me.
I found this to be a helpful starting point:
https://curl.se/libcurl/c/smtp-mail.html
There are two main problems with your code:
Your read_function didn't keep track of how much of the payload has been read so it would keep giving the same content to libcurl over and over and never signal the end of the message.
You were setting CURLOPT_MAIL_RCPT to a string when in fact it should be a struct curl_slist * because there can be multiple recipients.
Here is a fixed example that I tested on my computer and it worked. Private data at the top of the file was modified before posting.
#define USERNAME "david"
#define PASSWORD "xxxxx"
#define MAILTO "david#example.com"
#define MAILFROM "you#example.com"
#define SMTP "smtp://your.smtp.server.example.com:25"
#include <stdio.h>
#include <curl/curl.h>
const char * payload_text =
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n"
"To: " MAILTO "\r\n"
"From: " MAILFROM "\r\n"
"Subject: SMTP example message with libcurl 6\r\n"
"\r\n"
"Hello world!\r\n";
struct ReadData
{
explicit ReadData(const char * str)
{
source = str;
size = strlen(str);
}
const char * source;
size_t size;
};
size_t read_function(char * buffer, size_t size, size_t nitems, ReadData * data)
{
size_t len = size * nitems;
if (len > data->size) { len = data->size; }
memcpy(buffer, data->source, len);
data->source += len;
data->size -= len;
return len;
}
int main()
{
CURL * curl = curl_easy_init();
if (!curl)
{
fprintf(stderr, "curl_easy_init failed\n");
return 1;
}
curl_easy_setopt(curl, CURLOPT_USERNAME, USERNAME);
curl_easy_setopt(curl, CURLOPT_PASSWORD, PASSWORD);
curl_easy_setopt(curl, CURLOPT_URL, SMTP);
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, MAILFROM);
struct curl_slist * rcpt = NULL;
rcpt = curl_slist_append(rcpt, MAILTO);
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, rcpt);
ReadData data(payload_text);
curl_easy_setopt(curl, CURLOPT_READDATA, &data);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_function);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
// If your server doesn't have a proper SSL certificate:
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
return 0;
}
read_function: you are changing the local pointer buffer that does not affect the byte buffer of a caller. You should copy data to the pointed buffer
memcpy(buffer, data, len);
FYI sizeof(char) is guaranteed to be 1, thus is unneeded.
Another issue - the function never returns 0 that signals all data is sent, it sends the same data again and again. You should return 0 on a second call. Or set the length to the option CURLOPT_POSTFIELDSIZE_LARGE.
See the example smtp-mail.c

Curl data from Steam community market

I've been trying to fetch data from steam community market ,
Code :
#include <iostream>
#include <string>
#include <curl/curl.h>
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
int main(void)
{
CURL* curl;
CURLcode res;
std::string readBuffer;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://steamcommunity.com/market/priceoverview/?market_hash_name=AK-47%20%7C%20Redline%20%28Field-Tested%29&appid=730&currency=1");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
std::cout << readBuffer << std::endl;
}
return 0;
}
But when I run it , nothing show up .
Any help is appreciated ,
Thanks
curl doesn't follow redirects by default, and the site you mention uses those.
I had to turn on CURLOPT_FOLLOWLOCATION to make it work:
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // redirects
// bonus:
curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L); // corp. proxies etc.
Possible output:
{"success":true,"lowest_price":"$19.00","volume":"477","median_price":"$18.95"}
While debugging, you may want this option too to see what curl is up to:
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

How to use Curl in C++ to get http response string after sending http string to server

In a C ++ program I need to send an http message using Curl to another machine where is running a REST server written in C ++, and then collect the response from that server.
I am new to using Curl and have been looking at documentation and various examples on the web.
The source code of my program is the one attached below.
Sending the message to the server works, but I do not get the response the server sends me (not a timeout problem).
I would appreciate help with this, as I am not sure the code I use to get the response from the server is correct.
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <sstream>
#include <curl/curl.h>
size_t getAnswerFunction(void* ptr, size_t size, size_t nmemb, std::string* data) {
data->append((char*)ptr, size * nmemb);
return size * nmemb;
}
void sendDataAndGetAnswer(std::string data)
{
CURL *curl;
CURLcode res;
struct curl_slist *httpHeaders=NULL;
curl = curl_easy_init();
if (curl)
{
curl_global_init(CURL_GLOBAL_ALL);
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.100:15000");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
httpHeaders = curl_slist_append(httpHeaders, "MyProgram-Header");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, httpHeaders);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "MyAgent/1.0");
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 1000);
// .........................................
// MyProgram sends data.
// This works right.
// .........................................
res = curl_easy_perform(curl);
if (res != CURLE_OK)
std::cout << "curl_easy_perform() failed to send message: " << curl_easy_strerror(res) << std::endl;
// .........................................
// MyProgram get answer.
// This does not work.
// .........................................
std::string response_string;
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.100:15000");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, getAnswerFunction);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_string);
// getAnswerFunction waits at most 5000 ms.
// Afterwards, the flow of the program should continue even if there is no response.
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 5000);
res = curl_easy_perform(curl);
if (res == CURLE_OK)
std::cout << response_string;
else
std::cout << "curl_easy_perform() failed to get answer: " << curl_easy_strerror(res) << std::endl;
curl_easy_cleanup(curl);
curl_slist_free_all(httpHeaders);
}
}
int main(void)
{
while (1)
{
int valueVar = 0;
// Execute various statements and perform calculations.
// ...
// Calculate value here.
// ...
std::string msgToSend("CONTITION-IS-TRUE");
if (valueVar = 5)
sendDataAndGetAnswer(msgToSend);
sleep(10);
}
return 0;
}

C++ Telegram Bot POST request for updates no result

I'm tring to create a telegram bot. I' m first trying to get updates from the bot like said in the Telegram API with /getUpdates method.
With Postman the request is working good and I have all the data in json format.
Using cUrl I have no response and res is 0. Here there is the snippet of code:
#include <iostream>
#include <curl/curl.h>
#include <string>
using namespace std;
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
void getUpdates()
{
std::string readBuffer;
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "http://api.telegram.org/BOTTOKEN/getUpdates");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
struct curl_slist *headers = NULL;
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
std::cout << "Buffer content"<<readBuffer << std::endl;
long code = -1;
curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &code );
std::cout<<"HTTP Response Code: "<< code <<std::endl;
std::cout<<"Res: "<<res<<std::endl;
res = curl_easy_perform(curl);
}
}
int main()
{
getUpdates();
return 0;
}
Buffer content is empty and res is 0.
Could you give me any hints? Thank you!
I solved it! Here there is the updated code:
void getUpdates()
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "http://api.telegram.org/botyourtoken/getUpdates");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
struct curl_slist *headers = NULL;
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
std::string readBuffer;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
std::cout << "Buffer content: "<<std::endl;
std::cout<<readBuffer << std::endl;
}
curl_easy_cleanup(curl);
}
Thank you!

libcurl curl_easy_setopt "Unknown error"

I'm trying to use C++ cURL library for sending Json data via PUT method and my code looks something like this
CURL* m_curlHandle;
CURLcode m_returnValue;
//function1 start
curl_global_init(CURL_GLOBAL_ALL);
struct curl_slist* headers = NULL;
std::ostringstream oss;
struct curl_slist* slist = NULL;
slist = curl_slist_append(headers, "Accept: application/json");
slist = curl_slist_append(headers, "Content-Type: application/json");
slist = curl_slist_append(headers, "charsets: utf-8");
m_curlHandle = curl_easy_init();
if (!m_curlHandle)
// throw exception
curl_easy_setopt(m_curlHandle, CURLOPT_HTTPHEADER, headers);
//function1 end
//function2 start
std::string url = "some URL"; // my url
curl_easy_setopt(m_curlHandle, CURLOPT_URL, url.c_str());
unsigned int timeout = 5;
curl_easy_setopt(m_curlHandle, CURLOPT_TIMEOUT, timeout);
std::string localIp = "some IP"; // my IP address
curl_easy_setopt(m_curlHandle, CURLOPT_INTERFACE, localIp.c_str());
curl_easy_setopt(m_curlHandle, CURLOPT_CUSTOMREQUEST, "PUT");
std::string json = "some json struct"; //my json struct
curl_easy_setopt(m_curlHandle, CURLOPT_POSTFIELDS, json.c_str());
curl_easy_setopt(m_curlHandle, CURLOPT_WRITEFUNCTION, callbackWriter); //static size_t callbackWriter(char* buffer, size_t size, size_t nmemb, void* userp);
m_returnValue = curl_easy_perform(m_curlHandle);
//function2 end
I call function1 then function2 and the problem is that for all curl_easy_setopt calls I get error code 1685083487 and error description "Unknown error". So what may cause to a such result and how to fix this?
Thank you in advance!
I would use CURLOPT_POSTFIELDS instead, my func was something like this
void poolStr(const std::vector<unsigned char> &data, const std::string &url)
{
curl_global_init(CURL_GLOBAL_DEFAULT);
mCurl = curl_easy_init();
if(mCurl)
{
curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str());
curl_easy_setopt(mCurl, CURLOPT_POST, 1L);
curl_easy_setopt(mCurl, CURLOPT_POSTFIELDSIZE, data.size());
curl_easy_setopt(mCurl, CURLOPT_POSTFIELDS, &data[0]);
mChunk = curl_slist_append(mChunk, "Content-Type: application/binary");
mChunk = curl_slist_append(mChunk, "Expect:");
curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mChunk);
CURLcode res = curl_easy_perform(mCurl);
if(res != CURLE_OK)
{
LOGERROR << "curl_easy_perform() failed: " << curl_easy_strerror(res) << "\n Attepmt number: " << attempt;
}
else
{
LOGINFO << "Data being sent.";
}
}
}
}
and calling like poolStr(data, mHost);