I am new to c++. I am trying a tiny piece of code to interact with a local instance of InfluxDB.
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/curlver.h>
#include <curl/easy.h>
#include <curl/mprintf.h>
#include <curl/multi.h>
#include <curl/stdcheaders.h>
#include <curl/system.h>
#include <curl/typecheck-gcc.h>
using namespace std;
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); // Error here
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);
}
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);
}
When trying to build it, i get the following errors:
expected primary-expression before '__typeof__'
extend list of errors
Any ideas where it might come from ?
I am working on codeblocks 16.01, using GCC compiler on Ubuntu.
That was due to curl library not being linked to the compiler. The correct way to fix this in Codeblocks editor:
Project>Build options..>"Linker settings" tab
Under Link libraries, click on add, type the library name on the popping window, click OK, click OK again. And reboot Codeblocks.
Related
This question already has an answer here:
libcurl returns CURLcode 23
(1 answer)
Closed 7 months ago.
I am trying to get the idea about libcurl and I am trying to download simple photo from the url. But my program crashes when it goes inside curl_easy_perform() API. Any idea about it?
#include <stdio.h>
#include <curl/curl.h>
#include <QDebug>
#include <string>
int main(void)
{
CURL *curl;
FILE *fp;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
std::string url = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Nusfjord_road%2C_2010_09.jpg/1280px-Nusfjord_road%2C_2010_09.jpg";
//std::string url = "https://ra-jenkins-nyk01.siemens.net/job/TestCase_Logs/ws/OBU_Int_Build/TestCases/TC_30520_OBU_detects_dir_to_increase_whn_conf_increase_dir/TC_30520_OBU_detects_dir_to_increase_whn_conf_increase_dir.ctr";
char outfilename[FILENAME_MAX] = "D:/ankit.jpg";
curl = curl_easy_init();
if (curl)
{
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
//curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
if(res == CURLE_OK)
printf("Download Successful.");
else
printf("Not sucessful");
curl_easy_cleanup(curl);
fclose(fp);
}
return 0;
}
Compiler :- mingw
libcurl version :7.84.0
I wonder if you are using libcurl library as a win32 dll or static library, according to the libcurl official documentation, it says
If you are using libcurl as a win32 DLL, you MUST use a
CURLOPT_WRITEFUNCTION if you set this option or you will experience
crashes.
You may want to see in here: click
I did write a c++ code which automatically parses a webpage and open and parse some of their links. The point is that in these webpage there are some addresses which were redirected to other webpages. For example, when I try to open:
https://atlas.immobilienscout24.de/property-by-address?districtId=1276001006014
I ended up opening:
https://atlas.immobilienscout24.de/orte/deutschland/baden-württemberg/böblingen-kreis/leonberg
How could I get the url of the second page in C++?
In that particular case, it's given by the Location header in a 301 ("Moved Permanently") response (according to Chrome's Developer Tools).
If you set FOLLOWLOCATION to 0, you can prevent libcurl from following redirects, and then just examine the headers of the original response (or, probably better, query REDIRECT_URL for the information).
(Then you can perform a new request to the alternative URL, if you like.)
The default for this is 0, though, so you must be setting it to 1 yourself currently.
you could use CURLOPT_HEADERFUNCTION to inspect the headers and parse out the Location header, eg
#include <iostream>
#include <cstring>
#include <curl/curl.h>
size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata){
const std::string needle="Location: ";
if(nitems>needle.size()){
if(std::memcmp(&needle[0],buffer,needle.size()) == 0 ){
//todo: verify that im not off-by-one below.
((std::string*)userdata)->assign(&buffer[needle.size()],nitems-needle.size());
}
}
return nitems;
}
int main(int argc, char *argv[])
{
CURLcode ret;
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_URL, "https://atlas.immobilienscout24.de/property-by-address?districtId=1276001006014");
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(hnd, CURLOPT_NOBODY, 1L);
std::string redirect_url;
curl_easy_setopt(hnd,CURLOPT_HEADERDATA,&redirect_url);
curl_easy_setopt(hnd,CURLOPT_HEADERFUNCTION,header_callback);
ret = curl_easy_perform(hnd);
curl_easy_cleanup(hnd);
hnd = NULL;
std::cout << redirect_url;
return (int)ret;
}
.. but if you want the final url (in case of multiple redirects), rather than just "the second url", you should probably use CURLOPT_FOLLOWLOCATION and CURLINFO_EFFECTIVE_URL instead, eg
#include <iostream>
#include <cstring>
#include <curl/curl.h>
int main(int argc, char *argv[])
{
CURLcode ret;
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_URL, "https://atlas.immobilienscout24.de/property-by-address?districtId=1276001006014");
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(hnd, CURLOPT_NOBODY, 1L);
curl_easy_setopt(hnd,CURLOPT_FOLLOWLOCATION,1L);
ret = curl_easy_perform(hnd);
char *lolc;
curl_easy_getinfo(hnd, CURLINFO_EFFECTIVE_URL, &lolc);
std::string final_url(lolc);
curl_easy_cleanup(hnd);
hnd = NULL;
std::cout << final_url;
return (int)ret;
}
this approach is slower (have to do at least 1 more request upon redirect), but much simpler to implement and works on both redirected urls and non-redirected urls and multiple-redirected-urls alike.
I'm trying to teach myself C++ by writing a simple program that sends a cURL request to a JSON API, parses the data and then stores it either in a text document or database for a web application to access. I have done this task in PHP and figured C++ wouldn't be much harder but I can't even get cURL to return a string and display it.
I get this to compile with no errors, but the response "JSON data: " doesn't display anything where the JSON data should be.
Where did I go wrong? URL-to-API is the actual URL, so I believe I'm using a wrong setopt function, or not setting one. In PHP, "CURLOPT_RETURNTRANSFER" made it return as a string, but I get an error with it:
error: ‘CURLOPT_RETURNTRANSFER’ was not declared in this scope
curl_easy_setopt(curl, CURLOPT_RETURNTRANSFER, true);
I'm using g++ compiler on Ubuntu and added -lcurl to the command line argument.
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <curl/curl.h>
//#include "json.hpp"
using namespace std;
//using json = nlohmann::json;
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 getJSON(string URL) {
CURL *curl;
CURLcode res;
string readBuffer;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); // follow redirect
//curl_easy_setopt(curl, CURLOPT_RETURNTRANSFER, true); // return as string
curl_easy_setopt(curl, CURLOPT_HEADER, false);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_URL, URL);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
return readBuffer;
}
return 0;
}
int main() {
string data = getJSON("URL-to-api");
cout << "JSON Data: \n" << data;
return 0;
}
When I uncomment the JSON for Modern C++ include and namespace line I get this error:
error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
Along with a bunch of errors for functions in that library. I just downloaded the most recent version of g++ before embarking on this project, so what do I need to do?
I'm using g++ 5.4.0 on Ubuntu.
UPDATE:
So I added a check under res = curl_easy_perform(curl) and it doesn't return the error message, and res gets displayed as 6. This seems to be much more difficult than it should be:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <curl/curl.h>
//#include "json.hpp"
using namespace std;
//using json = nlohmann::json;
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 getJSON(string URL) {
CURL *curl;
CURLcode res;
string readBuffer;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); // follow redirect
curl_easy_setopt(curl, CURLOPT_HEADER, false);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_URL, URL);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
cout << res << endl;
if (!res) {
cout << "cURL didn't work\n";
}
/* always cleanup */
curl_easy_cleanup(curl);
curl = NULL;
return readBuffer;
}
}
int main() {
string data = getData("");
cout << "JSON Data: \n" << data;
return 0;
}
I get the following output when I run the program:
6
JSON Data:
In PHP "CURLOPT_RETURNTRANSFER" made it return as a string but I get an error:
error: ‘CURLOPT_RETURNTRANSFER’ was not declared in this scope
curl_easy_setopt(curl, CURLOPT_RETURNTRANSFER, true);
There is no CURLOPT_RETURNTRANSFER option documented for curl_easy_setopt(). I think that is an option specify to PHP's curl_exec() function, which doesn't exist in CURL itself. CURLOPT_WRITEFUNCTION is the correct way to go in this situation.
When I uncomment the JSON for Modern C++ include and namespace line I get:
error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
The error is self-explanatory. Your JSON library requires C++11 but you are not compiling with C++11 enabled. Some modern compilers still default to an older C++ version (usually C++98) and require you to explicitly enable C++11 (or later) when invoking the compiler on the command line, or in your project makefile configuration.
In the case of g++, the current version (8.2) defaults to (the GNU dialect of) C17 for C and C++14 for C++, if not specified otherwise via the -std parameter. Your version (5.4) defaults to (the GNU dialect of) C11 and C++98, respectively.
UPDATE: there are other mistakes in your code:
You are passing a std::string object to curl_easy_setopt() where a char* pointer is expected for CURLOPT_URL. You need to change this:
curl_easy_setopt(curl, CURLOPT_URL, URL);
To this instead:
curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
You are not testing the return value of curl_easy_perform() correctly. Per the documentation, curl_easy_perform() returns 0 (CURLE_OK) on success, and non-zero on error, so you need to change this:
if (!res)
To this instead:
if (res != CURLE_OK)
So I added a check under res = curl_easy_perform(curl) ..., and res gets displayed as 6.
That is CURLE_COULDNT_RESOLVE_HOST, which makes sense as your updated example is passing a blank URL to getJSON():
string data = getJSON(""); // should be "URL-to-api" instead!
I have a raspberry pi that is running a c++ program. It now needs to talk to the Parse.com cloud so it seems the REST API is the best choice. I've been programming for a year and have truly hit a wall here.
EDIT: I've been able to get the code below to run. It successfully posts "south" in a new row under the "direction" column. I had to link my compiler to -lcurl.
My remaining question is how can I in this syntax add conditions to the query? For me the limiting query is
WHERE hardwareType = 2.
I can also GET all the results of my parse table if I comment out the CURLOPT_POSTFIELDS line inside curl_easy_init. How can I limit this request with the same query quoted above?
#include <iostream>
#include <curl/curl.h>
#include <string>
#include <sstream>
#include <stdexcept>
using namespace std;
int main()
{
CURL *curl;
CURLcode res;
struct curl_slist *headerlist=NULL;
headerlist = curl_slist_append( headerlist, "X-Parse-Application-Id: aaaaaaaaaaa");
headerlist = curl_slist_append( headerlist, "X-Parse-REST-API-Key: bbbbbbbbbbbbbbbb");
headerlist = curl_slist_append( headerlist, "Content-Type: application/json");
//headerlist = curl_slist_append(headerlist, "-d '{"direction":"south"}'");
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_URL, "https://api.parse.com/1/classes/testing");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"direction\" : \"south\"}");
res = curl_easy_perform(curl);
if(res != CURLE_OK){
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
}
}
does anyone knows the exact syntax for using elasticsearch with libcurl?
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:9200/bro-201409170900/http/ZinAvJ-ETT-mycy2jyRkdg/_update -d");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"script\" : \"ctx._source.longitude += 3\"}");
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 1;
}
This code does ont update the longitude parameter and I don't know why.
One should not specify the "-d' in the url. The command line tool is just build on top of libcurl.
If you want to see what the c code for the post request would look like you could use the libcurl option with command line .
example :
curl localhost:9200/bro-201409170900/http/ZinAvJ-ETT-mycy2jyRkdg/… -d '{ "script" : "ctx._source.longitude += 2"}' --libcurl output.c
A simple "C" implementation would look something on these lines
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
char *postFields = "{\"script\" : \"ctx._source.longitude += 3\"}";
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:9200/bro-201409170900/http/ZinAvJ-ETT-mycy2jyRkdg/_update");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl,CURLOPT_POSTFIELDS,postFields);
curl_easy_setopt(curl,CURLOPT_POSTFIELDSIZE,strlen(postFields));
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return res;
}