Giter Club home page Giter Club logo

curlcpp's Introduction

curlcpp

An object-oriented C++ wrapper for cURL tool

If you want to know a bit more about cURL and libcurl, you should go on the official website http://curl.haxx.se/

Donate

Help me to improve this project!

Donate button

Compile and link manually

Standalone (static library)

cd build
cmake ..
make

Standalone (dynamic/shared library)

cd build
cmake .. -DBUILD_SHARED_LIBS=SHARED
make

Note: cURL >= 7.34.0 is required.

When linking curlcpp to your application don't forget to also link curl. Example:

g++ -std=c++11 example.cpp -I/usr/local/include/curlcpp/ -lcurlcpp -lcurl 

Submodule

When using a git submodule and CMake-buildsystem, add the following lines to your CMakeLists.txt:

ADD_SUBDIRECTORY(ext/curlcpp) # Change `ext/curlcpp` to a directory according to your setup
INCLUDE_DIRECTORIES(${CURLCPP_SOURCE_DIR}/include)

Install via Homebrew

curlcpp is now available also via homebrew package manager:

brew install curlcpp

Examples

Here are some usage examples. You will find more examples in the test folder!

Here's an example of a simple HTTP request to get google web page, using the curl_easy interface:

  • Simple request

#include "curlcpp/curl_easy.h"

using curl::curl_easy;
using curl::curl_easy_exception;
using curl::curlcpp_traceback;

/**
 * This example shows how to make a simple request with curl.
 */
int main() {
    // Easy object to handle the connection.
    curl_easy easy;

    // Add some options.
    easy.add<CURLOPT_URL>("http://<your_url_here>");
    easy.add<CURLOPT_FOLLOWLOCATION>(1L);

    try {
        easy.perform();
    } catch (curl_easy_exception &error) {
    	// If you want to print the last error.
        std::cerr<<error.what()<<std::endl;
    }
    return 0;
}
  • Extract session information

If you want to get information about the current curl session, you could do:

#include "curlcpp/curl_easy.h"
#include "curlcpp/curl_ios.h"
#include "curlcpp/curl_exception.h"

using std::ostringstream;

using curl::curl_easy;
using curl::curl_easy_exception;
using curl::curlcpp_traceback;
using curl::curl_ios;

/**
 * This example shows how to use the easy interface and obtain 
 * information about the current session.
 */
int main(int argc, const char **argv) {
    // Let's declare a stream
    ostringstream stream;

    // We are going to put the request's output in the previously declared stream
    curl_ios<ostringstream> ios(stream);

    // Declaration of an easy object
    curl_easy easy(ios);

    // Add some option to the curl_easy object.
    easy.add<CURLOPT_URL>("http://<your_url_here>");
    easy.add<CURLOPT_FOLLOWLOCATION>(1L);

    try {
        easy.perform();

		// Retrieve information about curl current session.
		auto x = easy.get_info<CURLINFO_CONTENT_TYPE>();

		/**
		 * get_info returns a curl_easy_info object. With the get method we retrieve
		 * the std::pair object associated with it: the first item is the return code of the
		 * request. The second is the element requested by the specified libcurl macro.
		 */
		std::cout<<x.get()<<std::endl;

    } catch (curl_easy_exception &error) {
		// If you want to print the last error.
		std::cerr<<error.what()<<std::endl;

		// If you want to print the entire error stack you can do
		error.print_traceback();
    }
    return 0;
}
  • HTTP Post

Here's instead, the creation of an HTTPS POST login form:

#include <string>

#include "curlcpp/curl_easy.h"
#include "curlcpp/curl_pair.h"
#include "curlcpp/curl_form.h"
#include "curlcpp/curl_exception.h"

using std::string;

using curl::curl_form;
using curl::curl_easy;
using curl::curl_pair;
using curl::curl_easy_exception;
using curl::curlcpp_traceback;

int main(int argc, const char * argv[]) {
    curl_form form;
    curl_easy easy;

    // Forms creation
    curl_pair<CURLformoption,string> name_form(CURLFORM_COPYNAME,"user");
    curl_pair<CURLformoption,string> name_cont(CURLFORM_COPYCONTENTS,"you username here");
    curl_pair<CURLformoption,string> pass_form(CURLFORM_COPYNAME,"passw");
    curl_pair<CURLformoption,string> pass_cont(CURLFORM_COPYCONTENTS,"your password here");
    
    try {
        // Form adding
        form.add(name_form,name_cont);
        form.add(pass_form,pass_cont);
        
        // Add some options to our request
        easy.add<CURLOPT_URL>("http://<your_url_here>");
        easy.add<CURLOPT_SSL_VERIFYPEER>(false);
        easy.add<CURLOPT_HTTPPOST>(form.get());
        // Execute the request.
        easy.perform();

    } catch (curl_easy_exception &error) {
        // If you want to get the entire error stack we can do:
        curlcpp_traceback errors = error.get_traceback();
        // Otherwise we could print the stack like this:
        error.print_traceback();
    }
    return 0;
}
  • Store response in a file

And if we would like to put the returned content in a file? Nothing easier than:

#include <iostream>
#include <ostream>
#include <fstream>

#include "curlcpp/curl_easy.h"
#include "curlcpp/curl_ios.h"
#include "curlcpp/curl_exception.h"

using std::cout;
using std::endl;
using std::ostream;
using std::ofstream;

using curl::curl_easy;
using curl::curl_ios;
using curl::curl_easy_exception;
using curl::curlcpp_traceback;

int main(int argc, const char * argv[]) {
    // Create a file
    ofstream myfile;
    myfile.open ("/path/to/your/file");
    
    // Create a curl_ios object to handle the stream
    curl_ios<ostream> writer(myfile);
    // Pass it to the easy constructor and watch the content returned in that file!
    curl_easy easy(writer);
    
    // Add some option to the easy handle
    easy.add<CURLOPT_URL>("http://<your_url_here>");
    easy.add<CURLOPT_FOLLOWLOCATION>(1L);
    try {
        // Execute the request
        easy.perform();

    } catch (curl_easy_exception &error) {
		// If you want to print the last error.
		std::cerr<<error.what()<<std::endl;

		// If you want to print the entire error stack you can do
		error.print_traceback();
    }
    myfile.close();
    return 0;
}
  • Store response in a variable

Not interested in files? So let's put the request's output in a variable!

#include <iostream>
#include <ostream>

#include "curlcpp/curl_easy.h"
#include "curlcpp/curl_form.h"
#include "curlcpp/curl_ios.h"
#include "curlcpp/curl_exception.h"

using std::cout;
using std::endl;
using std::ostringstream;

using curl::curl_easy;
using curl::curl_ios;
using curl::curl_easy_exception;
using curl::curlcpp_traceback;

int main() {
    // Create a stringstream object
    ostringstream str;
    // Create a curl_ios object, passing the stream object.
    curl_ios<ostringstream> writer(str);
    
    // Pass the writer to the easy constructor and watch the content returned in that variable!
    curl_easy easy(writer);
    // Add some option to the easy handle
    easy.add<CURLOPT_URL>("http://<your_url_here>");
    easy.add<CURLOPT_FOLLOWLOCATION>(1L);

    try {
        easy.perform();

        // Let's print the stream content
        cout<<str.str()<<endl;

    } catch (curl_easy_exception &error) {
		// If you want to print the last error.
		std::cerr<<error.what()<<std::endl;

		// If you want to print the entire error stack you can do
		error.print_traceback();
    }
    return 0;
}
  • Sender/Receiver

I have implemented a sender and a receiver to make it easy to use send/receive without handling buffers. For example, a very simple send/receiver would be:

#include <iostream>
#include <string>

#include "curlcpp/curl_easy.h"
#include "curlcpp/curl_form.h"
#include "curlcpp/curl_pair.h"
#include "curlcpp/curl_receiver.h"
#include "curlcpp/curl_exception.h"
#include "curlcpp/curl_sender.h"

using std::cout;
using std::endl;
using std::string;

using curl::curl_form;
using curl::curl_easy;
using curl::curl_sender;
using curl::curl_receiver;
using curl::curl_easy_exception;
using curl::curlcpp_traceback;

int main(int argc, const char * argv[]) {
    // Simple request
    string request = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
    // Creation of easy object.
    curl_easy easy;
    try {
        easy.add<CURLOPT_URL>("http://<your_url_here>");
        // Just connect
        easy.add<CURLOPT_CONNECT_ONLY>(true);
        // Execute the request.
        easy.perform();

    } catch (curl_easy_exception &error) {
        // If you want to get the entire error stack we can do:
        curlcpp_traceback errors = error.get_traceback();
        // Otherwise we could print the stack like this:
        error.print_traceback();
    }
    
    // Creation of a sender. You should wait here using select to check if socket is ready to send.
    curl_sender<string> sender(easy);
    sender.send(request);
    // Prints che sent bytes number.
    cout<<"Sent bytes: "<<sender.get_sent_bytes()<<endl;

    for(;;) {
        // You should wait here to check if socket is ready to receive
        try {
            // Create a receiver
            curl_receiver<char, 1024> receiver;
            // Receive the content on the easy handler
            receiver.receive(easy);
            // Prints the received bytes number.
            cout<<"Receiver bytes: "<<receiver.get_received_bytes()<<endl;

        } catch (curl_easy_exception &error) {
            // If any errors occur, exit from the loop
            break;
        }
    }
    return 0;
}
  • Multi interface example

The following example shows ho to use the curl MULTI interface.

I have implemented a sender and a receiver to make it easy to use send/receive without handling buffers. For example, a very simple send/receiver would be:

#include <iostream>
#include <ostream>

#include "curlcpp/curl_easy.h"
#include "curlcpp/curl_multi.h"
#include "curlcpp/curl_ios.h"

using curl::curl_easy;
using curl::curl_multi;
using curl::curl_ios;
using curl::curl_easy_exception;
using curl::curlcpp_traceback;

/**
 * This example shows how to make multiple requests
 * using curl_multi interface.
 */
int main() {
    std::vector<std::string> urls;
    urls.emplace_back("https://google.com");
    urls.emplace_back("https://facebook.com");
    urls.emplace_back("https://linkedin.com");

    // Create a vector of curl easy handlers.
    std::vector<curl_easy> handlers;

    // Create a vector of curl streams.
    std::vector<curl_ios<std::ostringstream>> streams;

    // Create the curl easy handler and associated the streams with it.
    for (const auto & url : urls) {
        auto *output_stream = new std::ostringstream;
        curl_ios<std::ostringstream> curl_stream(*output_stream);

        curl_easy easy(curl_stream);
        easy.add<CURLOPT_URL>(url.c_str());
        easy.add<CURLOPT_FOLLOWLOCATION>(1L);

        streams.emplace_back(curl_stream);
        handlers.emplace_back(easy);
    }

    // Create a map of curl pointers to output streams.
    std::unordered_map<CURL*, curl_ios<std::ostringstream>*> easy_streams;
    for (int i = 0; i < handlers.size(); ++i) {
        easy_streams[handlers.at(i).get_curl()] = (curl_ios<std::ostringstream>*)&streams.at(i);
    }

    // Add all the handlers to the curl multi object.
    curl_multi multi;
    multi.add(handlers);

    try {
        // Start the transfers.
        multi.perform();

        // Until there are active transfers, call the perform() API.
        while (multi.get_active_transfers()) {
            multi.perform();

            // Extracts the first finished request.
            std::unique_ptr<curl_multi::curl_message> message = multi.get_next_finished();
            if (message != nullptr) {
                const curl_easy *handler = message->get_handler();

                // Get the stream associated with the curl easy handler.
                curl_ios<std::ostringstream> stream_handler = *easy_streams[handler->get_curl()];

                auto content = stream_handler.get_stream()->str();
                auto url = handler->get_info<CURLINFO_EFFECTIVE_URL>();
                auto response_code = handler->get_info<CURLINFO_RESPONSE_CODE>();
                auto content_type = handler->get_info<CURLINFO_CONTENT_TYPE>();
                auto http_code = handler->get_info<CURLINFO_HTTP_CODE>();

                std::cout << "CODE: " << response_code.get()
                          << ", TYPE: " << content_type.get()
                          << ", HTTP_CODE: " << http_code.get()
                          << ", URL: " << url.get()
                          << ", CONTENT: " << content.substr(0, 10) + " ... "
                          << std::endl;
            }
        }

        // Free the memory allocated for easy streams.
        for (auto stream : streams) {
            delete stream.get_stream();
        }

    } catch (curl_easy_exception &error) {
        // If you want to print the last error.
        std::cerr<<error.what()<<std::endl;
    }
    return 0;
}

curlcpp's People

Contributors

arun-anbumani-auth avatar chemrat avatar desertkun avatar dvd0101 avatar fferflo avatar gigagg avatar gontsharuk avatar guijan avatar hatkirby avatar jacobmao avatar josephp91 avatar kaned1as avatar lunixoid avatar magister avatar markcallen avatar matiu2 avatar memcorrupt avatar mihir3445 avatar mplough-tenable avatar nobbz avatar prateek9623 avatar qqiangwu avatar rubdos avatar sav avatar susnux avatar thoronador avatar tiwoc avatar webmaster128 avatar wise86-android avatar xeverous avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

curlcpp's Issues

Error Building Library

I'm trying to build this right now but am getting errors on undeclared identifiers and such:

[ 12%] Building CXX object src/CMakeFiles/curlcpp.dir/curl_easy.cpp.o
In file included from /Users/evilflyingtoaster/Developer/CPP/curlcpp/src/curl_easy.cpp:6:
/Users/evilflyingtoaster/Developer/CPP/curlcpp/include/curl_easy.h:838:31: error: use of undeclared identifier 'CURLOPT_PINNEDPUBLICKEY'
        CURLCPP_DEFINE_OPTION(CURLOPT_PINNEDPUBLICKEY, const char*);
                              ^
/Users/evilflyingtoaster/Developer/CPP/curlcpp/include/curl_easy.h:47:33: note: expanded from macro 'CURLCPP_DEFINE_OPTION'
    template <> struct option_t<opt> {\
                                ^
/Users/evilflyingtoaster/Developer/CPP/curlcpp/include/curl_easy.h:841:31: error: use of undeclared identifier 'CURLOPT_UNIX_SOCKET_PATH'
        CURLCPP_DEFINE_OPTION(CURLOPT_UNIX_SOCKET_PATH, const char*);
                              ^
/Users/evilflyingtoaster/Developer/CPP/curlcpp/include/curl_easy.h:47:33: note: expanded from macro 'CURLCPP_DEFINE_OPTION'
    template <> struct option_t<opt> {\
                                ^
/Users/evilflyingtoaster/Developer/CPP/curlcpp/include/curl_easy.h:844:31: error: use of undeclared identifier 'CURLOPT_SSL_VERIFYSTATUS'; did you mean 'CURLOPT_SSL_VERIFYHOST'?
        CURLCPP_DEFINE_OPTION(CURLOPT_SSL_VERIFYSTATUS, long);
                              ^~~~~~~~~~~~~~~~~~~~~~~~
                              CURLOPT_SSL_VERIFYHOST
/Users/evilflyingtoaster/Developer/CPP/curlcpp/include/curl_easy.h:47:33: note: expanded from macro 'CURLCPP_DEFINE_OPTION'
    template <> struct option_t<opt> {\
                                ^
/usr/include/curl/curl.h:1090:3: note: 'CURLOPT_SSL_VERIFYHOST' declared here
  CINIT(SSL_VERIFYHOST, LONG, 81),
  ^
/usr/include/curl/curl.h:815:24: note: expanded from macro 'CINIT'
#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
                       ^
<scratch space>:164:1: note: expanded from here
CURLOPT_SSL_VERIFYHOST
^
In file included from /Users/evilflyingtoaster/Developer/CPP/curlcpp/src/curl_easy.cpp:6:
/Users/evilflyingtoaster/Developer/CPP/curlcpp/include/curl_easy.h:844:9: error: redefinition of 'curl::detail::option_t<CURLOPT_SSL_VERIFYHOST>'
        CURLCPP_DEFINE_OPTION(CURLOPT_SSL_VERIFYSTATUS, long);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/evilflyingtoaster/Developer/CPP/curlcpp/include/curl_easy.h:47:24: note: expanded from macro 'CURLCPP_DEFINE_OPTION'
    template <> struct option_t<opt> {\
                       ^~~~~~~~~~~~~
/Users/evilflyingtoaster/Developer/CPP/curlcpp/include/curl_easy.h:314:9: note: previous definition is here
        CURLCPP_DEFINE_OPTION(CURLOPT_SSL_VERIFYHOST, long);
        ^
/Users/evilflyingtoaster/Developer/CPP/curlcpp/include/curl_easy.h:47:24: note: expanded from macro 'CURLCPP_DEFINE_OPTION'
    template <> struct option_t<opt> {\
                       ^
4 errors generated.
make[2]: *** [src/CMakeFiles/curlcpp.dir/curl_easy.cpp.o] Error 1
make[1]: *** [src/CMakeFiles/curlcpp.dir/all] Error 2
make: *** [all] Error 2

I'm not sure if this is an error on my end...?

EDIT: Yes error on my end.

C++ `using` in header files

Some (most) of the header files in curlcpp have multiple using statements in the first lines of the file, this pollutes the top level namespace with standard library classes and curlcpp classes in user application files which simply want to use include curlcpp as a library and defeats the purpose of the namespace.

The solution would be to move any using statements to the innermost scope, or to remove them altogether.

See also: http://julipedia.meroh.net/2013/12/header-files-avoid-c-using-directives.html

alternative from C callback function to c++11 lambdas?

Because of CURLOPT_PROGRESSFUNCTION require interoperability to c++ using static member function, that is very costly for multithread code. Declaring private instance member data class doesn't compile even on VS2015 on windows. I m still thinking how to solve this, but that seems would be too much reinvent the wheel and losing much libcurl event system. I know here the root cause problem is on it's libcurl callback and need some ideas..

curl_easy_info<char*>::get when value is NULL

curl_easy::get_info returns a curl_easy_info, which usually makes its value available via curl_easy_info::get, but for char* types the template specialization converts the value to an std::string. This causes an exception (with an unhelpful error message) to be raised if the info value was null.

Specific example: I've been encountering an issue with CURLINFO_CONTENT_TYPE. The documentation for CURLINFO_CONTENT_TYPE states that its value can be null if "the server didn't send a valid Content-Type header or that the protocol used doesn't support this." I've been encountering issues where the following code raises an exception because of this:

auto content_type = handle.get_info<CURLINFO_CONTENT_TYPE>().get();

It'd be nice to be able to at least check before calling get that the info value wasn't null, because currently there is no way to know as far as I can tell.

Exception after setting CURLOPT_HTTP_VERSION to CURL_HTTP_VERSION_2_0

Hello!

I tried to built the first example, and it works well. Next I tried to add http2 support to it:

easy.add<CURLOPT_HTTP_VERSION>(3);

and after that I got the follow error:

terminate called after throwing an instance of 'curl::curl_easy_exception'
  what():  std::exception
Aborted (core dumped)
~> curl -V
curl 7.49.0 (x86_64-pc-linux-gnu) libcurl/7.49.0 OpenSSL/1.0.2h zlib/1.2.8
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP UnixSockets

Undefined symbols for architecture x86_64

Running on a mac using gcc-4.9 (also tried and got the same error with the provided xcode c++ compiler), I get this error. This is using the project as a submodule and following the README step by step. Here is my CMakeList.txt and error when I try to make. Any ideas?

cmake_minimum_required(VERSION 2.8)
project (rest_test)

ADD_SUBDIRECTORY(lib/curlcpp)
INCLUDE_DIRECTORIES(${CURLCPP_SOURCE_DIR}/include)

add_executable (rest_test rest_test.cc)
Linking CXX executable rest_test
Undefined symbols for architecture x86_64:
  "curl::curl_exception::traceback", referenced from:
      curl::curl_exception::what() in rest_test.cc.o
      curl::curl_exception::print_traceback() const in rest_test.cc.o
  "curl::curl_exception::curl_exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
      curl::curl_easy_exception::curl_easy_exception(CURLcode, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) in rest_test.cc.o
  "curl::curl_exception::~curl_exception()", referenced from:
      curl::curl_easy_exception::~curl_easy_exception() in rest_test.cc.o
  "curl::curl_easy::perform()", referenced from:
      _main in rest_test.cc.o
  "curl::curl_easy::curl_easy()", referenced from:
      _main in rest_test.cc.o
  "curl::curl_easy::~curl_easy()", referenced from:
      _main in rest_test.cc.o
  "typeinfo for curl::curl_exception", referenced from:
      typeinfo for curl::curl_easy_exception in rest_test.cc.o
  "vtable for curl::curl_exception", referenced from:
      curl::curl_exception::curl_exception(curl::curl_exception const&) in rest_test.cc.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "_curl_easy_setopt", referenced from:
      void curl::curl_easy::add<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(curl::curl_pair<CURLoption, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >) in rest_test.cc.o
      void curl::curl_easy::add<long>(curl::curl_pair<CURLoption, long>) in rest_test.cc.o
  "_curl_easy_strerror", referenced from:
      curl::curl_easy_exception::curl_easy_exception(CURLcode, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) in rest_test.cc.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [rest_test] Error 1
make[1]: *** [CMakeFiles/rest_test.dir/all] Error 2
make: *** [all] Error 2

get_info(CURLINFO_COOKIELIST) not referenced

Before all, thank you for your work, very useful.
I built your library on Ubuntu 14.04, using libcurl 7.35 (after removing line 276 of curl_easy.h, because it caused compiling error).
Then I moved header files in /usr/include/curlcpp, libcurlcpp.a in /usr/lib.

Source code of the simple test program is

#include <curlcpp/curl_easy.h>
using curl::curl_easy;

int main(int argc, const char **argv) {
    curl_easy easy;
    easy.add(curl_pair<CURLoption,string>(CURLOPT_URL,"http://www.google.it") );
    easy.add(curl_pair<CURLoption,long>(CURLOPT_FOLLOWLOCATION,1L));
    easy.add(curl_pair<CURLoption,string>(CURLOPT_COOKIEFILE,""));
    try {
        easy.perform();
        auto pippo = easy.get_info(CURLINFO_COOKIELIST);
        for(auto item : *pippo)
        {
            std::cout << item << ", " << std::endl;
        }
        std::cout << std::endl;
    } catch (curl_easy_exception &error) {
        // If you want to get the entire error stack we can do:
        std::vector<std::pair<std::string,std::string>> errors = error.get_traceback();
        // Otherwise we could print the stack like this:
        error.print_traceback();
        // Note that the printing the stack will erase it
    }
    std::cin.get();
    return 0;
}

I compiled succesfully (g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.cpp"), but linking (g++ -o "testCurlCpp" ./main.o -lcurl -lcurlcpp) fails saying

main.cpp:15: undefined reference to "curl::curl_easy::get_info(CURLINFO) const".
Removing line 15 all works fine.
Thank you.

[Headers] segmentation fault on init / add

I have tested this library, but I always got a segmentation fault in:
void curl_header::add(const string header)

After some tests I noticed it is this line:
this->headers = curl_slist_append(this->headers,header.c_str());

I compiled against libcurl 7.38.0 and compiled with no special flags (except maybe -fPIC).
My example to reproduce:

std::initializer_list<std::string> headers = {
    "User-Agent: Mozilla/5.0",
    "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Encoding: gzip,deflate"};
std::ostringstream resultStream;
curl_writer writer(resultStream);
curl_form form;
curl_easy easy(writer);
curl_header header(headers);
//Never reaches this point```

problem with CURLOPT_POSTFIELDS not working

This fails:

easy.add(curl_pair<CURLoption, string>(CURLOPT_POSTFIELDS, "This will fail"));
easy.perform();

I think this is because the scope of the string only lasts as long as the call, but internally a pointer is kept to the raw string data.
You probably should take an internal copy of the string somewhere before converting it to a C char buffer.

I'm not sure if this applies to other calls too....

To get this to work correctly I had to do this:

const std::string data("This will work");
easy.add(curl_pair<CURLoption, string>(CURLOPT_POSTFIELDS, data));
easy.perform():

deallocate memory problem

in file curl_form.cpp line 104, function add, the new_files array allocated by calloc, to deallocate it should use free. please check.

missing: CURL_LIBRARY CURL_INCLUDE_DIR

I'm new to curl, I hope anyone could help to solve this
I have installed curl from http://www.confusedbycode.com/curl/
when I'm trying cmake for visual studio v12 2013..I'm getting following error

missing: CURL_LIBRARY CURL_INCLUDE_DIR

This is the cmake log:
The C compiler identification is MSVC 18.0.30723.0
The CXX compiler identification is MSVC 18.0.30723.0
Check for working C compiler using: Visual Studio 12 2013 Win64
Check for working C compiler using: Visual Studio 12 2013 Win64 -- works
Detecting C compiler ABI info
Detecting C compiler ABI info - done
Check for working CXX compiler using: Visual Studio 12 2013 Win64
Check for working CXX compiler using: Visual Studio 12 2013 Win64 -- works
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
CMake Error at C:/Program Files (x86)/CMake/share/cmake-3.0/Modules/FindPackageHandleStandardArgs.cmake:136 (message):
Could NOT find CURL (missing: CURL_LIBRARY CURL_INCLUDE_DIR)
Call Stack (most recent call first):
C:/Program Files (x86)/CMake/share/cmake-3.0/Modules/FindPackageHandleStandardArgs.cmake:343 (_FPHSA_FAILURE_MESSAGE)
C:/Program Files (x86)/CMake/share/cmake-3.0/Modules/FindCURL.cmake:61 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
CMakeLists.txt:7 (FIND_PACKAGE)

Configuring incomplete, errors occurred!

curl_ios error with std::fstream and std::stringstream

hello,
i'm currently developing a game and i'm coding an updater for it
this is the compilation log from MinGW and code::blocks ide:
`
mt build log
Build started on: 09-02-2016 at 13:59.00
Build ended on: 09-02-2016 at 13:59.15

-------------- Build: Debug in mt (compiler: GNU GCC Compiler)---------------
g++.exe -std=c++14 -Wall -fpermissive -g -IF:\projects\cpp\mt\include -c F:\projects\cpp\mt\src\curl_cookie.cpp -o obj\Debug\src\curl_cookie.o
g++.exe -std=c++14 -Wall -fpermissive -g -IF:\projects\cpp\mt\include -c F:\projects\cpp\mt\src\curl_easy.cpp -o obj\Debug\src\curl_easy.o
g++.exe -std=c++14 -Wall -fpermissive -g -IF:\projects\cpp\mt\include -c F:\projects\cpp\mt\src\curl_exception.cpp -o obj\Debug\src\curl_exception.o
g++.exe -std=c++14 -Wall -fpermissive -g -IF:\projects\cpp\mt\include -c F:\projects\cpp\mt\src\curl_form.cpp -o obj\Debug\src\curl_form.o
g++.exe -std=c++14 -Wall -fpermissive -g -IF:\projects\cpp\mt\include -c F:\projects\cpp\mt\src\curl_header.cpp -o obj\Debug\src\curl_header.o
g++.exe -std=c++14 -Wall -fpermissive -g -IF:\projects\cpp\mt\include -c F:\projects\cpp\mt\src\curl_info.cpp -o obj\Debug\src\curl_info.o
g++.exe -std=c++14 -Wall -fpermissive -g -IF:\projects\cpp\mt\include -c F:\projects\cpp\mt\src\curl_multi.cpp -o obj\Debug\src\curl_multi.o
g++.exe -std=c++14 -Wall -fpermissive -g -IF:\projects\cpp\mt\include -c F:\projects\cpp\mt\src\curl_share.cpp -o obj\Debug\src\curl_share.o
g++.exe -std=c++14 -Wall -fpermissive -g -IF:\projects\cpp\mt\include -c F:\projects\cpp\mt\src\keyhook.cpp -o obj\Debug\src\keyhook.o
g++.exe -std=c++14 -Wall -fpermissive -g -IF:\projects\cpp\mt\include -c F:\projects\cpp\mt\src\updater.cpp -o obj\Debug\src\updater.o
F:\projects\cpp\mt\src\keyhook.cpp: In function 'void install_keyhook()':
F:\projects\cpp\mt\src\keyhook.cpp:59:96: warning: invalid conversion from 'LRESULT ()(int, LPARAM, WPARAM) {aka long int ()(int, long int,
unsigned int)}' to 'HOOKPROC {aka long int (attribute((stdcall)) )(int, unsigned int, long int)}' [-fpermissive]
keyhk_installed=hk=SetWindowsHookEx( WH_KEYBOARD_LL, keyboard_hook, GetModuleHandle(nullptr), 0);
^
In file included from C:/Dev-Cpp/i686-w64-mingw32/include/windows.h:72:0,
from F:\projects\cpp\mt\src\keyhook.cpp:6:
C:/Dev-Cpp/i686-w64-mingw32/include/winuser.h:3840:27: note: initializing argument 2 of 'HHOOK
__ SetWindowsHookExA(int, HOOKPROC, HINSTANCE, DWORD)'
WINUSERAPI HHOOK WINAPI SetWindowsHookExA (int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId);
^
F:\projects\cpp\mt\src\keyhook.cpp:59:16: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
keyhk_installed=hk=SetWindowsHookEx( WH_KEYBOARD_LL, keyboard_hook, GetModuleHandle(nullptr), 0);
^
g++.exe -o bin\Debug\mt.exe obj\Debug\src\curl_cookie.o obj\Debug\src\curl_easy.o obj\Debug\src\curl_exception.o obj\Debug\src\curl_form.o obj\Debug\src\curl_header.o
obj\Debug\src\curl_info.o obj\Debug\src\curl_multi.o obj\Debug\src\curl_share.o obj\Debug\src\keyhook.o obj\Debug\src\updater.o
In file included from F:\projects\cpp\mt\include/curl_easy.h:36:0,
from F:\projects\cpp\mt\src\updater.hpp:9,
from F:\projects\cpp\mt\src\updater.cpp:8:
F:\projects\cpp\mt\include/curl_ios.h: In instantiation of 'curl::curl_ios::curl_ios(T&, curlcpp_callback_type) [with T = std::__cxx11::basic_stringstream;
curlcpp_callback_type = unsigned int ()(void, unsigned int, unsigned int, void_); size_t = unsigned int]':
F:\projects\cpp\mt\src\updater.cpp:21:22: required from here
F:\projects\cpp\mt\include/curl_ios.h:69:81: error: cannot convert 'std::__cxx11::basic_stringstream' to 'std::__cxx11::basic_stringstream'
in initialization
curl_ios(T &stream, curlcpp_callback_type callback_ptr) : stream(stream) {
^
F:\projects\cpp\mt\include/curl_ios.h: In instantiation of 'curl::curl_ios::curl_ios(T&, curlcpp_callback_type) [with T = std::basic_fstream;
curlcpp_callback_type = unsigned int (
)(void
, unsigned int, unsigned int, void_); size_t = unsigned int]':
F:\projects\cpp\mt\src\updater.cpp:21:22: required from here
F:\projects\cpp\mt\include/curl_ios.h:69:81: error: cannot convert 'std::basic_fstream' to 'std::basic_fstream_' in initialization
Process terminated with status 1 (0 minute(s), 15 second(s))
2 error(s), 6 warning(s) (0 minute(s), 15 second(s))
and these are my declared variables that are related to curlcpp these are in updater class
std::stringstream xml_data; //the xml data string update file
std::fstream writer; //the file writer stream
curl::curl_iosstd::stringstream xmlcontents; //the contents of xml file
curl::curl_iosstd::fstream filewriter; //for the update file
curl::curl_easy e; //for getting the xml file that refers to update download link
curl::curl_easy downloader; //for getting the update file
now, in the constructor:
updater::updater():
writer("mtsetup.exe", ios::binary|ios::out|ios::trunc),
xmlcontents(xml_data, nullptr),
filewriter(writer, nullptr),
e(xmlcontents),
downloader(filewriter)
`
here i get errors, and i think those are related to curl_ios.h
thanks

`CMakeLists.txt` uses the disallowed `LOCATION` target property.

CMake Warning (dev) at external/curlcpp/CMakeLists.txt:29 (get_property):
  Policy CMP0026 is not set: Disallow use of the LOCATION target property.
  Run "cmake --help-policy CMP0026" for policy details.  Use the cmake_policy
  command to set the policy and suppress this warning.

  The LOCATION property should not be read from target "curlcpp".  Use the
  target name directly with add_custom_command, or use the generator
  expression $<TARGET_FILE>, as appropriate.

This warning is for project developers.  Use -Wno-dev to suppress it.

Is this a real problem or should it be ignored? (This is my first time using CMake.)

[RFC] are the `curl_multi::get_info` and `curl_multi::is_finished` methods broken?

IIUC the documentation every messages are returned only once and then removed from the internal handle.

But curl_multi::is_finished consumes all the queue searching for a specific easy handle, discarding the messages it is not interested in.

auto m = curl::curl_multi{};

m.add(easy1);
m.add(easy2);

// do something

std::cout << m.is_finished(easy1) << std::endl;
std::cout << m.is_finished(easy2) << std::endl;

The first call to curl_multi::is_finished could discard a message for easy2.

What if we add an unordered_map[easy_handle->message] in the curl_multi class in order to store the messages returned by curl_multi_info_read (overwrite the old ones should be ok)?

According to this answer on stackoverflow in order to reuse an easy handle you have to remove it, change and then re-add to the multi instance; if so we can cleanup the messages map during the remove phase.

Issue in README.md with curl::curl_easy::get_info();

In the examples given in the readme, it indicates that to retrieve the content-type from a curl::curl::easy request, you must do this:

// Retrieve information about curl current session.
auto x = easy.get_info(CURLINFO_CONTENT_TYPE);
// Print content type
std::cout << x.get().second << std::endl;

while in reality, the correct way to do this was

// Retrieve information about curl current session.
auto x = easy.get_info<CURL_CONTENT_TYPE>();
// Print out content type
std::cout << x.get() << std::endl;

Missing documentation

Hi!

I have had a look at curlcpp as a cURL wrapper for a C++ project I am working on.

While the API of curlcpp seems to be generally nice, the lack of documentation makes it nearly impossible to use curlcpp properly. I have, for example, been trying to write a code snippet which will translate the following curl command line call into C++ code, to no avail. I have no idea how CURLOPT_PUT works.

This is what I am trying to express in C++ using your library:

curl -H "Content-Type: application/json" -X PUT -d '{"username":"abc","password":"abc"}' http://localhost:10443/v0.1/metrics/windows/1442

Is there a way to achieve that? I'm surprised that CURLOPT_PUT doesn't take a string analog to CURLOPT_HTTPPOST to be send to the server. It takes a variable of type long, but there isn't really an explanation what that variable is supposed to be.

Would be great to have some sort of documentation of the API.

Thanks,
Adrian

Potential memory leak in several places

Example from the source code:

void curl_easy::escape(string &url) {
    char *url_encoded = curl_easy_escape(this->curl,url.c_str(),(int)url.length());
    if (url_encoded == nullptr) {
        throw curl_easy_exception("Null pointer intercepted",__FUNCTION__);
    }
    url = string(url_encoded);  // << HERE
    curl_free(url_encoded);
}

Here, if std::string constructor throws url_encoded will not be deallocated.
The same goes for curl_easy::unescape function.

There are no any way to send file by post

i mean, there are no anyway at the moment to do something like this
curl_formadd(&post, &last,
CURLFORM_COPYNAME, "file",
CURLFORM_FILE, "C:\rect.jpg",
CURLFORM_END);

curl_formadd(&post, &last,
CURLFORM_PTRNAME, "fileupload",
CURLFORM_BUFFER, "image",
CURLFORM_BUFFERPTR, png.GetOutputStreamBuffer()->GetBufferStart(),
CURLFORM_BUFFERLENGTH, png.GetOutputStreamBuffer()->GetBufferSize(),
CURLFORM_CONTENTTYPE, "image/png",
CURLFORM_END);

Compiling under Fedora 20/libcurl 7.32.0 doesn not work

/home/rsmet/src/sf.net/githubpp/curlcpp/include/curl_easy.h:280:31: error: ‘CURLOPT_DEPRECATED72’ was not declared in this scope
         CURLCPP_DEFINE_OPTION(CURLOPT_DEPRECATED72, long);
                               ^
/home/rsmet/src/sf.net/githubpp/curlcpp/include/curl_easy.h:47:33: note: in definition of macro ‘CURLCPP_DEFINE_OPTION’
     template <> struct option_t<opt> {\
                                 ^
/home/rsmet/src/sf.net/githubpp/curlcpp/include/curl_easy.h:47:36: error: template argument 1 is invalid
     template <> struct option_t<opt> {\
                                    ^
/home/rsmet/src/sf.net/githubpp/curlcpp/include/curl_easy.h:280:9: note: in expansion of macro ‘CURLCPP_DEFINE_OPTION’
         CURLCPP_DEFINE_OPTION(CURLOPT_DEPRECATED72, long);

Apparently, the #if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM > 0x072500 block fails, but commenting out so it will define the CURLOPT_OBSOLETE72 doesn't work either.

Any clue? I first tried as a submodule, but compiling it like in the README gives the same error.

qt c++ error: curl/curl.h: No such file or directory

I downloaded the libcURL source code and imported the headers and source into my .pro file and it seems to find all the libraries except for the main one.

dies on:

include <curl/curl.h>

.pro file contains:

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = RESTtest
TEMPLATE = app

SOURCES += main.cpp
mainwindow.cpp
../../../../../Users/Brad2/Documents/GitHub/curlcpp/src/CurlMulti.cpp
../../../../../Users/Brad2/Documents/GitHub/curlcpp/src/CurlHeader.cpp
../../../../../Users/Brad2/Documents/GitHub/curlcpp/src/CurlVersion.cpp
../../../../../Users/Brad2/Documents/GitHub/curlcpp/src/CurlEasy.cpp
../../../../../Users/Brad2/Documents/GitHub/curlcpp/src/CurlShare.cpp
../../../../../Users/Brad2/Documents/GitHub/curlcpp/src/CurlMessage.cpp
../../../../../Users/Brad2/Documents/GitHub/curlcpp/src/CurlHttpPost.cpp

HEADERS += mainwindow.h
../../../../../Users/Brad2/Documents/GitHub/curlcpp/include/CurlEasy.h
../../../../../Users/Brad2/Documents/GitHub/curlcpp/include/CurlInterface.h
../../../../../Users/Brad2/Documents/GitHub/curlcpp/include/CurlMulti.h
../../../../../Users/Brad2/Documents/GitHub/curlcpp/include/CurlPair.h
../../../../../Users/Brad2/Documents/GitHub/curlcpp/include/CurlVersion.h
../../../../../Users/Brad2/Documents/GitHub/curlcpp/include/CurlHttpPost.h
../../../../../Users/Brad2/Documents/GitHub/curlcpp/include/CurlHeader.h
../../../../../Users/Brad2/Documents/GitHub/curlcpp/include/CurlShare.h
../../../../../Users/Brad2/Documents/GitHub/curlcpp/include/CurlMessage.h
../../../../../Users/Brad2/Documents/GitHub/curlcpp/include/CurlError.h

FORMS += mainwindow.ui

INCLUDEPATH += "../../../../../Users/Brad2/Documents/GitHub/curlcpp/include"
INCLUDEPATH += "../../../../../Users/Brad2/Documents/GitHub/curlcpp/src"

curl_exception::what()

In curl_exception, we have two what() with distinct return type and are selected based on whether the exception object is constant. This will definitely confuse our user.

eg.

catch (curl_exception& e) {
    const auto& ce = e;

    std::vector<std::pair<std::string, std::string>> cwhat = ce.what();
    const char* ewhat = e.what();
}

This seems nonsence. So why not just rename the new what function as trace_stack() or something else?

Wrap curl_slist

namespace curl {

    class slist {
    private:
        struct curl_slist* list = nullptr;
    public:

        void append(std::string s) {
            list = curl_slist_append(list, s.c_str());
        }

        void add(std::string s) {
            append(s);
        }

        struct curl_slist* operator*() {
            return list;
        }

        slist& operator=(const slist&) = delete;

        slist& operator=(slist&& s) {
            if (list != nullptr) {
                curl_slist_free_all(list);
            }
            list = s.list;
            s.list = nullptr;

            return *this;
        }

        slist(std::string s) {
            list = curl_slist_append(list, s.c_str());
        };

        slist() {

        };

        ~slist() {
            if (list != nullptr) {
                curl_slist_free_all(list);
            }
        }
    };
}

Usage:

curl::slist list("Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");

memory corruption possibly caused by curl_easy

We are having a memory corruption problem that seems to be caused by the creation of the curl_easy object on the stack. If we return string() immediately after creating the object, we see memory corruption. If we return before creating the object, the corruption doesn't occur. We also note problems and crashes with gethostname (see stack trace below). These tests are being run on Ubnutu 14.02 Linux and with gcc 4.8.4.

const std::string TestClass::SendRequest(const string &request) {
LOG(LogLevel::Debug, request);

        // Create a ostringstream object to receive the response body
        ostringstream body_var;
        ostringstream header_var;

        // The "body" stream will put the body content into "body_var"
        curl_ios<ostringstream> body(body_var);

        // The "header" stream will put the headers into "header_var"
        curl_ios<ostringstream> header(header_var);

        // Easy object to handle the connection.
        curl_easy easy;

        return string();

}
#0 __tsearch (key=key@entry=0x7fffeb5eaf58, vrootp=vrootp@entry=0x2500435455002e28,

compar=compar@entry=0x7ffff4e4c610 <known_compare>) at tsearch.c:250
#1 0x00007ffff4e4d21f in __GI___nss_lookup_function (ni=ni@entry=0x2500435455002e00,

fct_name=fct_name@entry=0x7ffff4eae5e3 "gethostbyname4_r") at nsswitch.c:468
#2 0x00007ffff4dfc6a2 in gaih_inet (name=, service=, req=, pai=,

naddrs=) at ../sysdeps/posix/getaddrinfo.c:841
#3 0x00000000000003c2 in ?? ()
#4 0x0000000000000002 in ?? ()
#5 0x0000000000000000 in ?? ()

(gdb)

error: ‘curl_multi_wait’ was not declared in this scope

I'm using Debian Wheezy 7.5

in the curlcpp-master/build folder...
after I issue the command: cmake ..
and then I issue this command: make # -j2

This is the error I get:

curlcpp-master/src/curl_multi.cpp: In member function ‘void curl::curl_multi::wait(curl::curl_waitfd_, unsigned int, int, int_)’:
curlcpp-master/src/curl_multi.cpp:130:93: error: ‘curl_multi_wait’ was not declared in this scope
make[2]: *** [src/CMakeFiles/curlcpp.dir/curl_multi.cpp.o] Error 1
make[1]: *** [src/CMakeFiles/curlcpp.dir/all] Error 2
make: *** [all] Error 2

curl_interface is not thread safe

According to documentation of curl_global_init(3), this function is not thread safe. It is said that you can't call it in threaded environment. Since curl_interface is inherited by curl_easy and similar classes, they can't be safely used in multithreaded program.

You can check sources of libcurl itself and look onto implementation.

  • curl_global_init() uses not-atomic counter initialized
  • curl_global_init() sets global variables such as Curl_cmalloc declared in lib/curl_memory.h;
    these functions are used everywhere in curl, imagine what could happen if it is partially-set
  • it calls various sublibrary initializers such as Curl_ssl_init() which are not safe too, underlying
    SSL library functions can be called from different thread
  • etc

You can read mailing lists there
http://curl.haxx.se/mail/lib-2008-02/0116.html
http://curl.haxx.se/mail/lib-2008-02/0124.html
http://curl.haxx.se/mail/lib-2008-02/0126.html

Even usage of mutex is not safe guarantee because some underlying library function can be called without that advisory lock.
But it is probably much better if you document it like "Simultaneous usage of any library libcurl depends on can lead to undefined behavior" and implement lock. It will protect code from double execution of curl_global_init(3) from curl_interface (remember, initialized variable inside curl_global_init(3) is not thread safe).
Another option is to break interface of the library and create global initializer object which should be created before usage of the library. It will init curl in constructor and cleanup in destructor.

Here is part of doc about thread safety:
This function is not thread safe. You must not call it when any other thread in the program (i.e. a thread sharing the same memory) is running. This doesn't just mean no other thread that is using libcurl. Because curl_global_init(3) calls functions of other libraries that are similarly thread unsafe, it could conflict with any other thread that uses these other libraries.

breaks on recent curl versions (7.0.38)

Breaks as the obsolete 72 was removed.

Patch:

--- a/include/curl_easy.h
+++ b/include/curl_easy.h
@@ -273,8 +273,8 @@ namespace curl  {
         /* Max amount of cached alive connections */
         CURLCPP_DEFINE_OPTION(CURLOPT_MAXCONNECTS, long);

-        CURLCPP_DEFINE_OPTION(CURLOPT_OBSOLETE72, long); /* OBSOLETE, do not use! */ 
+        /* 72 = OBSOLETE */

         /* 73 = OBSOLETE */

PR follows, but gotta run now... :(

Not compatible with libcurl 7.35.0

Failed compile with libcurl 7.35.0.
It seems use obsoleted one.

My environment is
Ubuntu 14.04 64bit
g++ 4.8.2

geniys@geni-u14-vm:~/Works/OSS/curlcpp/build$ cmake ..
-- The C compiler identification is GNU 4.8.2
-- The CXX compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found CURL: /usr/lib/x86_64-linux-gnu/libcurl.so (found suitable version "7.35.0", minimum required is "7.28.0") 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/geniys/Works/OSS/curlcpp/build
geniys@geni-u14-vm:~/Works/OSS/curlcpp/build$ make
Scanning dependencies of target curlcpp
[ 12%] Building CXX object src/CMakeFiles/curlcpp.dir/curl_easy.cpp.o
In file included from /home/geniys/Works/OSS/curlcpp/src/curl_easy.cpp:6:0:
/home/geniys/Works/OSS/curlcpp/include/curl_easy.h:276:31: error: ‘CURLOPT_OBSOLETE72’ was not declared in this scope
         CURLCPP_DEFINE_OPTION(CURLOPT_OBSOLETE72, long); /* OBSOLETE, do not use! */
                               ^
/home/geniys/Works/OSS/curlcpp/include/curl_easy.h:47:33: note: in definition of macro ‘CURLCPP_DEFINE_OPTION’
     template <> struct option_t<opt> {\
                                 ^
/home/geniys/Works/OSS/curlcpp/include/curl_easy.h:47:36: error: template argument 1 is invalid
     template <> struct option_t<opt> {\
                                    ^
/home/geniys/Works/OSS/curlcpp/include/curl_easy.h:276:9: note: in expansion of macro ‘CURLCPP_DEFINE_OPTION’
         CURLCPP_DEFINE_OPTION(CURLOPT_OBSOLETE72, long); /* OBSOLETE, do not use! */
         ^
make[2]: *** [src/CMakeFiles/curlcpp.dir/curl_easy.cpp.o] Error 1
make[1]: *** [src/CMakeFiles/curlcpp.dir/all] Error 2
make: *** [all] Error 2
geniys@geni-u14-vm:~/Works/OSS/curlcpp/build$ g++ --version
g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

geniys@geni-u14-vm:~/Works/OSS/curlcpp/build$

Thanks

Sending JSON data over POST

Hi, i'm tring to send json data over POST:

Here's my code

curl_easy easy;
curl_header header;
header.add("Content-Type: application/json");
easy.add(curl_pair<CURLoption,curl_header>(CURLOPT_HTTPHEADER, header));
easy.add(curl_pair<CURLoption,string>(CURLOPT_URL, "http://localhost:3000/activePlayers"));
easy.add(curl_pair<CURLoption,string>(CURLOPT_HTTPPOST,a));
try {
    easy.perform();
} catch (curl_easy_exception error) {
    // Print errors, if any
    error.print_traceback();
}

I get the following error:

ERROR: Out of memory ::::: FUNCTION: perform

Any idea how to set the application/json header and send JSON over POST ?

gcc6 warnings

Problem in noexcept + throw

./ext/curlcpp/src/cookie.cpp: In member function ‘curl::cookie* curl::cookie::set_secure(unsigned int)’:
./ext/curlcpp/src/cookie.cpp:114:95: warning: throw will always call terminate() [-Wterminate]
         throw new curl_easy_exception("The security can be 0 (false) or 1 (true)",__FUNCTION__);

Crotch (maybe logically there must be some else routine):

diff --git i/include/cookie.h w/include/cookie.h
index cf2f639..76ccf53 100644
--- i/include/cookie.h
+++ w/include/cookie.h
@@ -94,3 +94,3 @@ namespace curl {
          */
-        cookie *set_secure(const unsigned int) NOEXCEPT;
+        cookie *set_secure(const unsigned int) ;
         /**
@@ -166,2 +166,2 @@ namespace curl {

-#endif //CURLCPP_COOKIE_H
\ No newline at end of file
+#endif //CURLCPP_COOKIE_H
diff --git i/src/cookie.cpp w/src/cookie.cpp
index 939b1e3..e0cfccc 100644
--- i/src/cookie.cpp
+++ w/src/cookie.cpp
@@ -107,3 +107,3 @@ curl::cookie *curl::cookie::set_secure(const char *secure) NOEXCEPT {
 // Implementation of set_secure method.
-curl::cookie *curl::cookie::set_secure(const unsigned int secure) NOEXCEPT {
+curl::cookie *curl::cookie::set_secure(const unsigned int secure) {
     if (secure == 0) {

Questionable namespace usage.

What's the point of using a namespace when the code still uses C-style naming? (library_function). In my opinion it is like having to write std::std_cout.

wrong singleton paths in visual studio project

The included Visual Studio project has wrong path to the singleton sources.

the project tries to get them from the path

curlcpp\src\utilspp\singleton\LifetimeLibrary.cpp
curlcpp\src\utilspp\singleton\PrivateMembers.cpp

however the files are located at

curlcpp\src\utilspp\LifetimeLibrary.cpp
curlcpp\src\utilspp\PrivateMembers.cpp

unable to compile the post example

Hello,
I tried to compile the example with the http post login and I get this message.

g++ -std=c++11 postexample.cpp -L curlcpp/build/src/ -I curlcpp/include/ -lcurlcpp -lcurl -o
postexample :(
In file included from curlcpp/include/curl_easy.h:34:0,
from postexample.cpp:1:
curlcpp/include/curl_pair.h: In instantiation of ‘curl::curl_pair<T, std::basic_string >::curl_pair(T, const string&) [with T = CURLformoption; std::string = std::basic_string]’:
postexample.cpp:12:70: required from here
curlcpp/include/curl_pair.h:85:72: warning: comparison between ‘const enum CURLformoption’ and ‘enum CURLoption’ [-Wenum-compare]
curl_pair(const T option, const string &value) : option(option == CURLOPT_POSTFIELDS ? CURLOPT_COPYPOSTFIELDS : option), value(value) {};
^
curlcpp/include/curl_pair.h:85:94: warning: enumeral mismatch in conditional expression: ‘CURLoption’ vs ‘CURLformoption’ [-Wenum-compare]
curl_pair(const T option, const string &value) : option(option == CURLOPT_POSTFIELDS ? CURLOPT_COPYPOSTFIELDS : option), value(value) {};
^
In file included from curlcpp/include/curl_easy.h:34:0,
from postexample.cpp:1:
curlcpp/include/curl_pair.h:85:141: error: invalid conversion from ‘int’ to ‘CURLformoption’ [-fpermissive]
curl_pair(const T option, const string &value) : option(option == CURLOPT_POSTFIELDS ? CURLOPT_COPYPOSTFIELDS : option), value(value) {};

How to pass response to a variable?

I might just be being stupid, but it seems you can only either print the output or write it to a file?

How can you simply a request into a variable?

Cheers

curl_multi should not be copyable

Currently, curl_multi provides a copy constructor and a copy assignment operator.

The copy constructor actually creates a completely independent new multi handle but assigns message_queued and active_count, which does not make sense at all.

The assignment operator just initializes the new multi handle.

I believe that the copy constructor and assignment operators should be deleted (= delete),
and move constructor and move assignment provided instead if necessary.

Update

Similarly, I think that curl_easy should not be copyable by default either. Otherwise it is too easy to copy accidentally (for example, when storing a curl_easy in a container). Instead, there should be a .clone() method for the case there the user wants to clone the handle.

Update2

Actually, this issues can be easily solved by wrapping the handle into a std::unique_ptr like this:

class curl_multi
{
    struct deleter
    {
        void operator()(CURLM* h) const
        {
            curl_multi_cleanup(h);
        }
    };

    std::unique_ptr<CURLM, deleter> handle_;

    // other members here...
}

This will automatically provide safe moving and prohibit copying and automatically provide a destructor.

Doesn't build on Ubuntu 15.04

$ LC_ALL=C apt-cache show libcurl4-openssl-dev
Package: libcurl4-openssl-dev
Priority: optional
Section: libdevel
Installed-Size: 1232
Maintainer: Ubuntu Developers <[email protected]>
Original-Maintainer: Alessandro Ghedini <[email protected]>
Architecture: amd64
Source: curl
Version: 7.38.0-3ubuntu2
Provides: libcurl-dev, libcurl-ssl-dev, libcurl3-dev, libcurl3-openssl-dev, libcurl4-dev
Depends: libcurl3 (= 7.38.0-3ubuntu2)
Suggests: libcurl4-doc, libcurl3-dbg, libidn11-dev, libkrb5-dev, libldap2-dev, librtmp-dev, libssl-dev, pkg-config, zlib1g-dev
Conflicts: libcurl4-gnutls-dev, libcurl4-nss-dev
Filename: pool/main/c/curl/libcurl4-openssl-dev_7.38.0-3ubuntu2_amd64.deb
Size: 252648
MD5sum: 776693e739d63610ed5699f922477c11
SHA1: 6bd217c3cc0363f2acbca72838001130ef102a00
SHA256: c743a29acad89eee05351b47a6d50b10b59a8a42ad3ce1fae8e05999c2e57a93
Description-en: development files and documentation for libcurl (OpenSSL flavour)
[...]
Description-md5: 9ef3e0d3a9a6f50f79b0deaff858c410
Multi-Arch: same
Homepage: http://curl.haxx.se
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Origin: Ubuntu
Supported: 9m



$ cmake .. -DCMAKE_BUILD_TYPE=Release -DWITHOUT_OCSP_STAPLING=1
-- The C compiler identification is Clang 3.6.1
-- The CXX compiler identification is Clang 3.6.1
-- Check for working C compiler: /opt/compiler/llvm-3.6/bin/clang
-- Check for working C compiler: /opt/compiler/llvm-3.6/bin/clang -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /opt/compiler/llvm-3.6/bin/clang++
-- Check for working CXX compiler: /opt/compiler/llvm-3.6/bin/clang++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found CURL: /usr/lib/x86_64-linux-gnu/libcurl.so (found suitable version "7.38.0", minimum required is "7.28.0")
CMake Warning (dev) at CMakeLists.txt:34 (get_property):
  Policy CMP0026 is not set: Disallow use of the LOCATION target property.
  Run "cmake --help-policy CMP0026" for policy details.  Use the cmake_policy
  command to set the policy and suppress this warning.

  The LOCATION property should not be read from target "curlcpp".  Use the
  target name directly with add_custom_command, or use the generator
  expression $<TARGET_FILE>, as appropriate.

This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: /home/thomas/development/ipgrep/curlcpp/build



$ make VERBOSE=1
/usr/bin/cmake -H/home/thomas/development/ipgrep/curlcpp -B/home/thomas/development/ipgrep/curlcpp/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/thomas/development/ipgrep/curlcpp/build/CMakeFiles /home/thomas/development/ipgrep/curlcpp/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/data/development/ipgrep/curlcpp/build'
make -f src/CMakeFiles/curlcpp.dir/build.make src/CMakeFiles/curlcpp.dir/depend
make[2]: Entering directory '/data/development/ipgrep/curlcpp/build'
cd /home/thomas/development/ipgrep/curlcpp/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/thomas/development/ipgrep/curlcpp /home/thomas/development/ipgrep/curlcpp/src /home/thomas/development/ipgrep/curlcpp/build /home/thomas/development/ipgrep/curlcpp/build/src /home/thomas/development/ipgrep/curlcpp/build/src/CMakeFiles/curlcpp.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/data/development/ipgrep/curlcpp/build'
make -f src/CMakeFiles/curlcpp.dir/build.make src/CMakeFiles/curlcpp.dir/build
make[2]: Entering directory '/data/development/ipgrep/curlcpp/build'
/usr/bin/cmake -E cmake_progress_report /home/thomas/development/ipgrep/curlcpp/build/CMakeFiles 1
[ 12%] Building CXX object src/CMakeFiles/curlcpp.dir/curl_easy.cpp.o
cd /home/thomas/development/ipgrep/curlcpp/build/src && /opt/compiler/llvm-3.6/bin/clang++   -DWITHOUT_OCSP_STAPLING -std=c++11 -O3 -DNDEBUG -I/home/thomas/development/ipgrep/curlcpp/include    -o CMakeFiles/curlcpp.dir/curl_easy.cpp.o -c /home/thomas/development/ipgrep/curlcpp/src/curl_easy.cpp
In file included from /home/thomas/development/ipgrep/curlcpp/src/curl_easy.cpp:6:
/home/thomas/development/ipgrep/curlcpp/include/curl_easy.h:838:31: error: use of undeclared identifier 'CURLOPT_PINNEDPUBLICKEY'
        CURLCPP_DEFINE_OPTION(CURLOPT_PINNEDPUBLICKEY, const char*);
                              ^
/home/thomas/development/ipgrep/curlcpp/include/curl_easy.h:47:33: note: expanded from macro 'CURLCPP_DEFINE_OPTION'
    template <> struct option_t<opt> {\
                                ^
/home/thomas/development/ipgrep/curlcpp/include/curl_easy.h:841:31: error: use of undeclared identifier 'CURLOPT_UNIX_SOCKET_PATH'
        CURLCPP_DEFINE_OPTION(CURLOPT_UNIX_SOCKET_PATH, const char*);
                              ^
/home/thomas/development/ipgrep/curlcpp/include/curl_easy.h:47:33: note: expanded from macro 'CURLCPP_DEFINE_OPTION'
    template <> struct option_t<opt> {\
                                ^
2 errors generated.
src/CMakeFiles/curlcpp.dir/build.make:54: recipe for target 'src/CMakeFiles/curlcpp.dir/curl_easy.cpp.o' failed
make[2]: *** [src/CMakeFiles/curlcpp.dir/curl_easy.cpp.o] Error 1
make[2]: Leaving directory '/data/development/ipgrep/curlcpp/build'
CMakeFiles/Makefile2:75: recipe for target 'src/CMakeFiles/curlcpp.dir/all' failed
make[1]: *** [src/CMakeFiles/curlcpp.dir/all] Error 2
make[1]: Leaving directory '/data/development/ipgrep/curlcpp/build'
Makefile:76: recipe for target 'all' failed
make: *** [all] Error 2

The same happens with g++ too. I am using the latest sources as of writing.

Use of undeclared identifier when building on OS X 10.10

Im trying to build the project on my OS X 10.10 machine and get the following errors.

/curlcpp/src/curl_easy.cpp:6:
include/curl_easy.h:838:31: error: use of undeclared identifier 'CURLOPT_PINNEDPUBLICKEY'
        CURLCPP_DEFINE_OPTION(CURLOPT_PINNEDPUBLICKEY, const char*);

/curlcpp/include/curl_easy.h:841:31: error: use of undeclared identifier 'CURLOPT_UNIX_SOCKET_PATH'
        CURLCPP_DEFINE_OPTION(CURLOPT_UNIX_SOCKET_PATH, const char*);

/curlcpp/include/curl_easy.h:844:31: error: use of undeclared identifier 'CURLOPT_SSL_VERIFYSTATUS'; did you mean 'CURLOPT_SSL_VERIFYHOST'?
        CURLCPP_DEFINE_OPTION(CURLOPT_SSL_VERIFYSTATUS, long);

/curlcpp/include/curl_easy.h:844:9: error: redefinition of 'curl::detail::option_t<CURLOPT_SSL_VERIFYHOST>'
        CURLCPP_DEFINE_OPTION(CURLOPT_SSL_VERIFYSTATUS, long);

Do curlcpp not support the OS X version of libcurl?

curl_easy::reset() causing CURLE_BAD_FUNCTION_ARGUMENT on perform()

Attempting to use this to setup and teardown an RTSP connection

Basic function call structure looks like this:

main()
{
    rtsp_test();
}

rtsp_test()
{
    curl::curl_global();
    curl::curl_easy easy_handle;

    rtsp_announce(easy_handle, ...);
    rtsp_setup(easy_handle, ...);
    rtsp_setup(easy_handle, ...);
    rtsp_record(easy_handle, ...);            // <------ error occurs within record()
    rtsp_describe(easy_handle, ...);
}

void rtsp_announce(curl::curl_easy& easy, ...){
    easy.reset();

    //add options

    try {
        easy.perform();
    }
    catch (curl::curl_easy_exception error) {
        //...
    }
}
void rtsp_setup(curl::curl_easy& easy, ...){
    //.... the same
}
void rtsp_record(curl::curl_easy& easy, ...){
    easy.reset();                //<----------------- potential cause of error

    //add options

    try {
        easy.perform();       //<--------------- returns CURLE_BAD_FUNCTION_ARGUMENT
    }
    catch (curl::curl_easy_exception error) {
        //...
    }
}
void rtsp_describe(curl::curl_easy& easy, ...){
    //.... the same
}

The call to easy.perform() within rtsp_record() throws an exception. The interesting thing is that the easy.perform() within rtsp_describe still works just fine. All of the calls perform fine except the call to rtsp_record().

accidental crash

I am using curlcpp in my iOS app, and sometimes it happens crash.
screen shot 2016-07-21 at 10 43 49 am

'NOEXCEPT' does not name a type

When I compile curlcpp on Windows with MinGW I get the following error:

$ make
Scanning dependencies of target curlcpp
[ 12%] Building CXX object src/CMakeFiles/curlcpp.dir/curl_easy.cpp.obj
[ 25%] Building CXX object src/CMakeFiles/curlcpp.dir/curl_header.cpp.obj
In file included from C:/curlcpp/src/curl_head
er.cpp:6:0:
C:/curlcpp/include/curl_header.h:66:22: error:
 expected ';' at end of member declaration
         ~curl_header() NOEXCEPT;
                      ^
C:/curlcpp/include/curl_header.h:66:24: error:
 'NOEXCEPT' does not name a type
         ~curl_header() NOEXCEPT;
                        ^
make[2]: *** [src/CMakeFiles/curlcpp.dir/curl_header.cpp.obj] Error 1
make[1]: *** [src/CMakeFiles/curlcpp.dir/all] Error 2
make: *** [all] Error 2

How can I fix this?

POST sample string reference error

In the post sample this line uses the "user" constant, but in curl_pair the value is a reference:
curl_pair<CURLformoption,string> name_form(CURLFORM_COPYNAME,"user");

It only works when changed like this because of the scope of the string:
std::string fieldName = "user"; curl_pair<CURLformoption,string> name_form(CURLFORM_COPYNAME, fieldName);

Maybe curl_pair should copy the value? But at least the sample should be changed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.