C++ Requests: Curl for People, a spiritual port of Python Requests.

Overview

C++ Requests: Curl for People

Documentation CI Gitter

Announcements

TLDR

C++ Requests is a simple wrapper around libcurl inspired by the excellent Python Requests project.

Despite its name, libcurl's easy interface is anything but, and making mistakes misusing it is a common source of error and frustration. Using the more expressive language facilities of C++11, this library captures the essence of making network calls into a few concise idioms.

Here's a quick GET request:

#include <cpr/cpr.h>

int main(int argc, char** argv) {
    cpr::Response r = cpr::Get(cpr::Url{"https://api.github.com/repos/whoshuu/cpr/contributors"},
                      cpr::Authentication{"user", "pass"},
                      cpr::Parameters{{"anon", "true"}, {"key", "value"}});
    r.status_code;                  // 200
    r.header["content-type"];       // application/json; charset=utf-8
    r.text;                         // JSON text string
    return 0;
}

And here's less functional, more complicated code, without cpr.

Documentation

Documentation
You can find the latest documentation here. It's a work in progress, but it should give you a better idea of how to use the library than the tests currently do.

Features

C++ Requests currently supports:

  • Custom headers
  • Url encoded parameters
  • Url encoded POST values
  • Multipart form POST upload
  • File POST upload
  • Basic authentication
  • Bearer authentication
  • Digest authentication
  • NTLM authentication
  • Connection and request timeout specification
  • Timeout for low speed connection
  • Asynchronous requests
  • 🍪 support!
  • Proxy support
  • Callback interfaces
  • PUT methods
  • DELETE methods
  • HEAD methods
  • OPTIONS methods
  • PATCH methods
  • Thread Safe access to libCurl
  • OpenSSL and WinSSL support for HTTPS requests

Planned

For a quick overview about the planed features, have a look at the next Milestones.

Usage

CMake

If you already have a CMake project you need to integrate C++ Requests with, the primary way is to use fetch_content. Add the following to your CMakeLists.txt.

include(FetchContent)
FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/libcpr/cpr.git
                         GIT_TAG beb9e98806bb84bcc130a2cebfbcbbc6ce62b335) # The commit hash for 1.7.2. Replace with the latest from: https://github.com/libcpr/cpr/releases
FetchContent_MakeAvailable(cpr)

This will produce the target cpr::cpr which you can link against the typical way:

target_link_libraries(your_target_name PRIVATE cpr::cpr)

That should do it! There's no need to handle libcurl yourself. All dependencies are taken care of for you.
All of this can be found in an example here.

Packages for Linux Distributions

Alternatively, you may install a package specific to your Linux distribution. Since so few distributions currently have a package for cpr, most users will not be able to run your program with this approach.

Currently, we are aware of packages for the following distributions:

If there's no package for your distribution, try making one! If you do, and it is added to your distribution's repositories, please submit a pull request to add it to the list above. However, please only do this if you plan to actively maintain the package.

Requirements

The only explicit requirements are:

  • a C++11 compatible compiler such as Clang or GCC. The minimum required version of GCC is unknown, so if anyone has trouble building this library with a specific version of GCC, do let me know
  • If you would like to perform https requests OpenSSL and its development libraries are required.

Building cpr - Using vcpkg

You can download and install cpr using the vcpkg dependency manager:

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install cpr

The cpr port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.

Building cpr - Using Conan

You can download and install cpr using the Conan package manager. Setup your CMakeLists.txt (see Conan documentation on how to use MSBuild, Meson and others). An example can be found here.

The cpr package in Conan is kept up to date by Conan contributors. If the version is out of date, please create an issue or pull request on the conan-center-index repository.

Comments
  • cmake config

    cmake config

    I'm still creating a FreeBSD port, and it would be great to have a cmake config for cpr in order to do stuff like find_package(cpr).

    Thank you very much in advance.

    opened by part1zano 30
  • progress callback draft

    progress callback draft

    Hi! I added an issue here #432 a few minutes ago, but then i realised that there was an already existing issue that's been open for quite a while sadly #111.

    This is a quick draft / example of adding a progress callback option, and it works 😄 . This allows us to create progress bars and also cancel any request early by returning a non zero value from the callback!

    If there's any chance of adding this and you want me to clean up anything, let me know! Thanks

    Tests Needed :rotating_light: Feature :sparkles: Documentation Needed :green_book: 
    opened by ITotalJustice 20
  • "free(): invalid pointer" when using CPR with conan

    Description

    When using CPR with conan I get this error when trying to run the binary

    free(): invalid pointer
    Aborted
    

    Expected Behavior

    Should work

    Actual Behavior

    It breaks

    Possible Fix

    Steps to Reproduce

    1. Use CPR with conan

    Context

    I was trying to reach out to a website and get the response body/text.

    Your Environment

    • Version used: 1.6.2
    • Where did you get it from (e.g. conan, vcpkg, master, ...): conan
    • Operating System and version: Linux ari-gentoo 5.14.2-gentoo #1 SMP Thu Sep 9 18:26:44 EEST 2021 x86_64 Intel(R) Core(TM) i3-8130U CPU @ 2.20GHz GenuineIntel GNU/Linux
    • Link to a small example: https://replit.com/@B00bleaTea/ghufhuerhyur4gyfghryfhryhfyufhurehufberfhberhbfhuerbfhuerf#main.cpp

    Run this when trying the example (in the shell tab):

    chmod a+rx ./build.sh
    
    ./build.sh
    
    ./bin/conantest 'https://google.com'
    
    Bug :bug: Needs Investigation :mag: 
    opened by TruncatedDinosour 17
  • Static linking (Windows)

    Static linking (Windows)

    Hello. I am trying to use a static version of the library installed through VCPKG using the command./vcpkg install cpr:x86-windows-static but i am getting many errors. image

    This are my settings: image image

    Bug :bug: Build :construction_worker: Windows :tv: 
    opened by John4266 17
  • Provide CPRConfig.cmake to allow easy find_package()

    Provide CPRConfig.cmake to allow easy find_package()

    I'm all but a cmake expert but if I interpret this http://www.cmake.org/cmake/help/git-master/manual/cmake-packages.7.html#creating-packages link and my cmake output correctly, supplying CPRConfig.cmake would allow downstream projects to include cpr as a dependency like this:

     set ( CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} vendor/cpr/)
     find_package ( CPR REQUIRED )
     include_directories ( ${CPR_INCLUDE_DIRS} )
    

    and then use ${CPR_LIBRARIES} in target_link_libraries(). Instead of vendoring it could also be installed in the system path getting rid of the first line in the snippet above.

    Documentation :books: Build :construction_worker: 
    opened by niklas88 17
  • Empty response text and status code 0 at example code

    Empty response text and status code 0 at example code

    Code

    #include <cpr/cpr.h>
    #include <iostream>
    
    int main(int argc, char** argv) {
        cpr::Response r = cpr::Get(cpr::Url{"https://api.github.com/repos/whoshuu/cpr/contributors"},
                          cpr::Authentication{"user", "pass"},
                          cpr::Parameters{{"anon", "true"}, {"key", "value"}});
        std::cout << r.status_code << std::endl << r.text;
        return 0;
    }
    

    Expected Behavior

    It should print the status code and the response body

    Actual Behavior

    It prints 0

    Your Environment

    • Where did you get it from (e.g. conan, vcpkg, master, ...): master
    • Operating System and version: MacOS 12.1
    • Build System: g++/clang++
    Needs Investigation :mag: 
    opened by Pxddyk45 16
  • How can I use cpr as a static linked library on Windows?

    How can I use cpr as a static linked library on Windows?

    Hiya. I got cpr and libcurl from vcpkg

    ./vcpkg install libcurl:x86-windows-static
    ./vcpkg install cpr:x86-windows-static
    

    Due to vcpkg having a static package for cpr, I just assume that it exists and works.

    Now.. it works. However, requires libcurl.dll and zlib1.dll in the app's directory. When I try to build with the runtime library as Multi-threaded (/MT), I get a bunch of errors from cpr

    1>cpr.lib(session.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in CMainWindow.obj
    1>cpr.lib(auth.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in CMainWindow.obj
    1>cpr.lib(cookies.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in CMainWindow.obj
    1>cpr.lib(digest.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in CMainWindow.obj
    1>cpr.lib(proxies.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in CMainWindow.obj
    1>cpr.lib(error.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in CMainWindow.obj
    1>cpr.lib(timeout.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in CMainWindow.obj
    1>cpr.lib(util.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in CMainWindow.obj
    1>cpr.lib(cprtypes.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in CMainWindow.obj
    

    Am I doing something wrong?

    Build :construction_worker: Question :question: Help Needed :tipping_hand_man: Windows :tv: 
    opened by shavitush 15
  • Add ability to install library and headers through CMake

    Add ability to install library and headers through CMake

    There are three competing pull requests right now that implement this. My laziness has unfortunately resulted in some duplicate work 😥 .

    #176 #132 #56

    Unbiased discussion on the pros and cons of each approach would be appreciated. The immediate goal is to make make install in a sane way. The long term goal is to make packaging the library (for something like Homebrew for instance) feasible so it can be distributed without git.

    Build :construction_worker: Discussion :interrobang: 
    opened by whoshuu 15
  • Problems with HTTPS requests.

    Problems with HTTPS requests.

    Description

    The problem occurs when I'm trying to send any type of request to an https server. With http it works just fine. If server supports both, http and https it also works when I'm trying to send https request. To make sure that issue is actual I tried to install libcpr on another computer, and it did the same. Moreover, I used libcpr for a month and there were no problems ever, but as soon as I reinstalled the library, this happened. Also, I tried to test libCurl, and it sends https requests to any server.

    Expected Behavior

    Sending HTTPS requests as always.

    Actual Behavior

    Does send only HTTP requests and returns code 0 when trying to send HTTPS.

    Your Environment

    • Version used: 1.7.2
    • Where did you get it from (e.g. conan, vcpkg, master, ...): vcpkg
    • Operating System and version: Windows 10 Pro 21H1, Build 19043.1526
    • Link to a small example: https://imgur.com/4TOPax9
    curl :globe_with_meridians: 
    opened by 1Klas 14
  • CPR on Raspberry Pi

    CPR on Raspberry Pi

    Hi there,

    For a home project I would like to use CPR on the raspberry pi 2b+. I made a small test program to read and write data to a Rest Api, but the POST request hangs forever and is not executed on the Rest Api. The GET request works fine. I build the the same code also on my desktop(Ubuntu 20.04 amd64) and that gives no problems. My first attempt was cross-compiling with various toolchains, but it always hangs on the POST/PUT request. Finally I did a local build on the raspberry pi and it kept hanging on the POST request.

    The c++ code is:

    #include <iostream>
    #include <cpr/cpr.h>
    #include "nlohmann/json.hpp"
    
    using json = nlohmann::json;
    
    int main()
    {
    	std::cout << "Hello World\n";
    
    	auto r = cpr::Get(cpr::Url("http://192.168.10.188:3001/environment?select=location,pressure"));
    
    		std::cout << r.status_code << std::endl;
    		std::cout << r.header["content-type"] << std::endl;
    		std::cout << r.text << std::endl;
    
    	json msg;
    	msg["location"] = "livingroom";
    	msg["temperature"] = 27.5;
    	msg["pressure"] = 1006.1;
    	msg["humidity"] = 61;
    	msg["time"] = "2020-07-01T13:21:22.18542+00:00";
    	std::cout << msg.dump() << std::endl;
    	r = cpr::Post(cpr::Url("http://192.168.10.188:3001/environment"),
    				  cpr::Header{{"Content-Type", "application/json"},
    							  {"Content-Length", std::to_string(msg.dump().length())}},
    				  cpr::Body(msg.dump()));
    
    	std::cout << r.status_code << std::endl;
    	std::cout << r.header["content-type"] << std::endl;
    	std::cout << r.text << std::endl;
    
    	return 0;
    }
    

    my makefile is:

    OBJECTS=build/main.o 
    
    BUILDDIR=build/
    SOURCEDIR=src/
    LIB=-L/usr/local/lib/ -L/usr/local/lib
    # include the src directory for rapidjson and spdlog includes
    INC=-Isrc
    MKDIR_P = mkdir -p
    
    .PHONY : all
    all: $(BUILDDIR)testCprSimple
    
    $(BUILDDIR)testCprSimple : $(OBJECTS)
    	g++ -o $(BUILDDIR)testCprSimple $(OBJECTS) $(LIB) -latomic -lcpr -lcurl
    
    $(BUILDDIR)main.o : $(SOURCEDIR)main.cpp
    	g++ -o $(BUILDDIR)main.o $(SOURCEDIR)main.cpp -std=c++14 $(INC) -g3 -O2 -Wall -c -fmessage-length=0
    
    # There are two reasons to use a phony target: 
    # to avoid a conflict with a file of the same name, and to improve performance. 	
    .PHONY: clean
    clean :
    	rm $(BUILDDIR)testCprSimple $(OBJECTS)
    # Tab must be used as indentation
    

    I am using 2020-02-13-raspbian-buster-lite as OS on the raspberry pi with gcc (Raspbian 8.3.0-6+rpi1) 8.3.0

    I have installed and build CPR successfully on the raspberry pi with:

    git clone https://github.com/whoshuu/cpr.git
    cd cpr
    git submodule update --init
    mkdir build; cd build
    cmake -DCMAKE_USE_OPENSSL=OFF ..
    make
    sudo make install
    

    The curl program itself is working with POST request on the pi: curl http://192.168.10.188:3001/environment -X POST -H "Content-Type: application/json" -d '{"location":"livingroom", "temperature":23.2,"pressure":1002.5, "humidity":49, "time":"2020-07-01T13:21:22.18542+00:00"}'

    Am i forgetting something for the raspberry pi / arm build or is it a bug? Thanks in advance for your help.

    Bug :bug: 
    opened by skipper85 14
  • HTTP Error 411 while making POST request to Microsoft Azure Workspace

    HTTP Error 411 while making POST request to Microsoft Azure Workspace

    I am trying to set up a remote log system on the Microsoft Azure Workspace. I am using cpr POST request to send sample JSON data over to the server. The code I used is as follows:

    #include <iostream>
    #include <map>
    #include <utility>
    #include <nlohmann/json.hpp>
    using json = nlohmann::json;
    #include <cpr/cpr.h>
    #include <time.h>
    using std::cout;
    using std::cerr;
    using std::endl;
    
    #include <string>
    using std::string;
    
    #include "cryptopp/cryptlib.h"
    using CryptoPP::Exception;
    
    #include "cryptopp/hmac.h"
    using CryptoPP::HMAC;
    
    #include "cryptopp/sha.h"
    using CryptoPP::SHA256;
    
    #include "cryptopp/base64.h"
    using CryptoPP::Base64Encoder;
    using CryptoPP::Base64Decoder;
    
    #include "cryptopp/filters.h"
    using CryptoPP::StringSink;
    using CryptoPP::StringSource;
    using CryptoPP::HashFilter;
    
    
    
    typedef unsigned char byte;
    
    string CUSTOMER_ID = "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
    string SHARED_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    string METHOD = "POST";
    string CONTENT_TYPE = "application/json";
    string RESOURCE = "/api/logs";
    string uri = "https://" + CUSTOMER_ID + ".ods.opinsights.azure.com/api/logs?api-version=2016-04-01";
    string uri2 = "https://postman-echo.com/post";
    
    string sign(string key, string plain)
    {
        string mac, encoded;
        try
        {
    
            HMAC< SHA256 > hmac((byte*)key.c_str(), key.length());
    
            StringSource(plain, true,
                         new HashFilter(hmac,
                                        new StringSink(mac)
                         ) // HashFilter
            ); // StringSource
        }
        catch(const CryptoPP::Exception& e)
        {
            cerr << e.what() << endl;
        }
    
        encoded.clear();
        StringSource(mac, true,
                     new Base64Encoder(
                             new StringSink(encoded)
                     ) // Base64Encoder
        ); // StringSource
    
        return encoded;
    }
    
    string getTimestamp()
    {
        char buf[1000];
        time_t now = time(0);
        //struct tm tm = *localtime(&now);
        struct tm *tm = gmtime(&now);
        strftime(buf, sizeof buf, "%a, %d %b %Y %H:%M:%S GMT", tm);
        cout << buf << endl;
        return buf;
    
    }
    
    string getSignature(const string& customer_id, const string& shared_key, const string& date, size_t content_length,
                        const string& method, const string& content_type, const string& resource)
    {
        string x_headers = "x-ms-date:" + date;
        string string_to_hash = (method + "\n" + std::to_string(content_length) + "\n" + content_type + "\n" + x_headers + "\n" + resource);
        string decoded_share_key;
        decoded_share_key.clear();
        StringSource(shared_key,true, new Base64Decoder( new StringSink(decoded_share_key)));
        string encoded_hash = sign(decoded_share_key,string_to_hash);
    
        string signature = "SharedKey "+ customer_id + ":" +encoded_hash;
                //SharedKey {customer_id}:{encoded_hash}
    
        cout << signature << endl;
    
        return signature;
    }
    
    
    void post(string customer_id, string shared_key, string body, string log_type)
    {
        string date = getTimestamp();
    
        string signature = getSignature(CUSTOMER_ID, SHARED_KEY, date,
                                        body.length(), METHOD,
                                        CONTENT_TYPE, RESOURCE);
    
        auto response = cpr::Post(cpr::Url(uri),
                                    cpr::Header{{"content-type",CONTENT_TYPE},
                                                {"Authorization",signature},
                                                {"log-type",log_type},
                                                {"x-ms-date", date},
                                                {"content-length",std::to_string(body.length())}},
                                    cpr::Body(body));
    
    
    
        cout << response.url << endl;
        try {
            json j = json::parse(response.text);
            cout << j.dump(4) << endl;
        }
        catch (std::exception& e) {
            cout << e.what() << endl << endl;
            cout << response.text << endl;
        }
        cout << response.status_code << endl;
        if(response.status_code!=200)
        {
           cout << response.error.message << endl;
        }
        cout << response.elapsed << endl;
    }
    
    
    int main() {
        
        string log_type = "LoggingTest";
    
        json log_msg;
        json msg;
        log_msg["property1"] = "value1";
    
        msg = {log_msg};
    
        post(CUSTOMER_ID, SHARED_KEY, msg.dump(), log_type);
    
    
        return 0;
    }
    

    However, I'm always getting the same error like this (from response.text) :

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
    <HTML><HEAD><TITLE>Length Required</TITLE>
    <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
    <BODY><h2>Length Required</h2>
    <hr><p>HTTP Error 411. The request must be chunked or have a content length.</p>
    </BODY></HTML>
    

    Things I have tried and the results:

    1. Added "content-length" header: Same error
    2. Tried sending empty body with content length zero: Same error
    3. Made POST request to Postman-echo service to see if the library is unable to forward all data: Results as follows -

    3.1 Sending JSON data with authorization header:

    {
        "args": {},
        "data": {},
        "files": {},
        "form": {},
        "headers": {
            "accept": "*/*",
            "authorization": "SharedKey xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "host": "postman-echo.com",
            "user-agent": "curl/7.47.0",
            "x-amzn-trace-id": "Root=1-5ebe2da5-2275dd11f1b39c54c33fa6df",
            "x-forwarded-port": "443",
            "x-forwarded-proto": "https"
        },
        "json": null,
        "url": "https://postman-echo.com/post"
    }
    

    Notice that even though I'm sending JSON data with the POST request, Postman-echo does not show it. This is strange because when I did the same thing using a Python script, the result showed me both the data as well as the authorization signature.

    3.2 Sending JSON data without authorization header:

    {
         "args": {},
        "data": [
            {
                "property1": "value1"
            }
        ],
        "files": {},
        "form": {},
        "headers": {
            "accept": "*/*",
            "content-length": "24",
            "content-type": "application/json",
            "host": "postman-echo.com",
            "log-type": "LoggingTest",
            "user-agent": "curl/7.47.0",
            "x-amzn-trace-id": "Root=1-5ebe2f54-bfcef7b08ee37ca8efe47d90",
            "x-forwarded-port": "443",
            "x-forwarded-proto": "https",
            "x-ms-date": "Fri, 15 May 2020 05:57:40 GMT"
        },
        "json": [
            {
                "property1": "value1"
            }
        ],
        "url": "https://postman-echo.com/post"
    }
    

    Then Postman-echo is showing me the json data sent.

    In my understanding, generated key is not wrong, since in that case, authorization failure is the first error. The same code above, written in Python3 and Python2 worked correctly. This was the link I was following: https://docs.microsoft.com/de-de/azure/azure-monitor/platform/data-collector-api

    Is there any known issue of similar kind in the cpr library? Please help.

    Bug :bug: curl :globe_with_meridians: 
    opened by prat33kg 14
  • PKCS#12 files for client authentication

    PKCS#12 files for client authentication

    Is your feature request related to a problem?

    curl built with SecureTransport

    https://github.com/curl/curl/blob/master/lib/vtls/sectransp.c#L1896 SSL: The Security framework only supports loading identities that are in PKCS#12 format.

    Possible Solution

    https://github.com/libcpr/cpr/blob/master/cpr/session.cpp#L495 If cert_type is p12 add CURLOPT_KEYPASSWD

    Alternatives

    No response

    Additional Context

    No response

    Feature :sparkles: Needs Investigation :mag: 
    opened by ioxuy 1
  • Load client cert from a buffer

    Load client cert from a buffer

    Is your feature request related to a problem?

    I have not found possibility to specify client SSL certificate from a buffer. Is there really no way of doing that?

    Possible Solution

    Add this possibility as for CaBuffer

    Alternatives

    No response

    Additional Context

    No response

    Feature :sparkles: Needs Investigation :mag: 
    opened by Chrys4lisfag 1
  • File Upload to S3 via Presigned URL

    File Upload to S3 via Presigned URL

    I am trying to write a function to upload a file to Amazon S3 using a presigned URL. I have written two implementations to do so, one using CPR and one using libcurl. The libcurl one is based on this file_upload.c example from curl's documentation.

    CPR:

    bool uploadToPresignedURL(std::string url, std::filesystem::path filePath) 
    {
    
        auto r = cpr::Put(cpr::Url{url.c_str()},
                          cpr::Multipart{{"file", cpr::File{filePath.c_str()}}});
        printf("Status code: %lu\n", r.status_code);
    
        return r.status_code == 200;
    
    }
    

    libcurl:

    bool uploadToPresignedURL_libcurl(std::string url, std::filesystem::path filePath) 
    {
    
        CURL *curl;
        CURLcode res;
        struct stat file_info;
        curl_off_t speed_upload, total_time;
        FILE *fd;
        bool uploaded = false;
    
        fd = fopen(filePath.c_str(), "rb"); /* open file to upload */
        if (!fd)
            return uploaded; /* cannot continue */
    
        /* to get the file size */
        if (fstat(fileno(fd), &file_info) != 0)
            return uploaded; /* cannot continue */
    
        curl = curl_easy_init();
        if (curl)
        {
            /* upload to this place */
            curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    
            /* tell it to "upload" to the URL */
            curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    
            /* set where to read from (on Windows you need to use READFUNCTION too) */
            curl_easy_setopt(curl, CURLOPT_READDATA, fd);
    
            /* and give the size of the upload (optional) */
            curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
    
            /* enable verbose for easier tracing */
            curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    
            res = curl_easy_perform(curl);
            /* Check for errors */
            if (res != CURLE_OK)
            {
                fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
            }
            else
            {
                uploaded = true;
                /* now extract transfer info */
                curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD_T, &speed_upload);
                curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &total_time);
    
                fprintf(
                    stderr,
                    "Speed: %lu bytes/sec during %lu.%06lu seconds\n",
                    (unsigned long)speed_upload,
                    (unsigned long)(total_time / 1000000),
                    (unsigned long)(total_time % 1000000));
            }
            /* always cleanup */
            curl_easy_cleanup(curl);
        }
        fclose(fd);
    
        return uploaded;
    
    }
    

    The libcurl implementation uploads the file properly with a 200. However, with the CPR implementation I am consistently getting a 403. The AWS keys are encoded in the URL in the Presigned URL. Is there something special I need to do to get the Url constructor to deal with them properly? When using the curl CLI, I need to surround the URL with 's or it also 403s.

    Bug :bug: Needs Investigation :mag: 
    opened by pwolfe1 10
  • MultiperformTenSessionsGetTest Test Case Fails on macOS Nondeterministic

    MultiperformTenSessionsGetTest Test Case Fails on macOS Nondeterministic

    Description

    On macOS systems the MultiperformTenSessionsGetTest test case fails nondeterministic. In case it fails, it gets an error indicating that the connection establishment failed inside curl.

    This issue still exists, even in case we update to curl 7.85.0.

    Example/How to Reproduce

    Execute the MultiperformTenSessionsGetTest test case on macOS. For this one first has to enable it again in the source code since I disabled it in #863 for macOS for now.

    TEST(MultiperformGetTests, MultiperformTenSessionsGetTest) {
        const size_t sessionCount = 10;
    
        MultiPerform multiperform;
        Url url{server->GetBaseUrl() + "/hello.html"};
        for (size_t i = 0; i < sessionCount; ++i) {
            std::shared_ptr<Session> session = std::make_shared<Session>();
            session->SetUrl(url);
            multiperform.AddSession(session);
        }
    
        std::vector<Response> responses = multiperform.Get();
    
        EXPECT_EQ(responses.size(), sessionCount);
        for (Response& response : responses) {
            EXPECT_EQ(std::string{"Hello world!"}, response.text);
            EXPECT_EQ(url, response.url);
            EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
            EXPECT_EQ(200, response.status_code);
            EXPECT_EQ(ErrorCode::OK, response.error.code);
        }
    }
    

    Possible Fix

    Unknown.

    Where did you get it from?

    GitHub (branch e.g. master)

    Additional Context/Your Environment

    • OS: macOS 12
    • Version: 1.9.x
    Bug :bug: curl :globe_with_meridians: CI :bricks: Needs Investigation :mag: 
    opened by COM8 0
  • Feature Request: Add method to easily add parameters to what's already in the session

    Feature Request: Add method to easily add parameters to what's already in the session

    Is your feature request related to a problem? Please describe. I'm currently implementing a client to communicate with the Binance api. Authentication on Binance involves doing an hmac sha256 hash on the query string and request body and then adding the hash to the query string. I determined that using an Interceptor is the best way to go about this, and here is my intercept function:

      cpr::Response BinanceClient::AuthInterceptor::intercept(cpr::Session& session)
      {
        spdlog::trace("AuthInterceptor");
        auto url = session.GetFullRequestUrl();
        std::string queryStr;
        auto found = url.find('?');
        if (found != std::string::npos)
        {
          queryStr = url.substr(found + 1) + "&";
          url = url.substr(0, found);
        }
        queryStr += "timestamp=" + std::to_string(getTimestamp_ms());
        auto hmac(utils::hmacSha256(queryStr, m_secretKey));
        session.SetParameters({});
        session.SetUrl(cpr::Url{url + "?" + queryStr + "&signature=" + hmac});
        session.SetHeader(cpr::Header{{"X-MBX-APIKEY", m_apiKey}});
    
        return proceed(session);
      }
    

    As you can see, I have to add the signature and the timestamp in a kinda janky way. Instead of adding the parameter, I instead clear the parameters and I add the signature onto the end of the Url. It works... it's just janky.

    Describe the solution you'd like It would be wonderful if there was an AddParameters() method so that instead of clearing the parameters and modifying the Url I could just do session.AddParameters({{"signature", hmac}});. Note: The parameter(s) would need to be added in a way that they are guaranteed to be in the query string in the order in which they're given, so just adding the one parameter would result in it beingat the end of the resultant query string.

    Describe alternatives you've considered We could be given access the the Parameters member ourselves, and then cpr::Parameters could be given a method to allow us to add parameters to it.

    Additional context Nope.

    Feature :sparkles: 
    opened by Triasmus 1
Releases(1.9.3)
  • 1.9.3(Nov 24, 2022)

    In this release we fixed a CMake crash caused by us adding custom build types for sanitizer builds. They now got replaced by CMake flags.

    • CPR_DEBUG_SANITIZER_FLAG_THREAD
    • CPR_DEBUG_SANITIZER_FLAG_ADDR
    • CPR_DEBUG_SANITIZER_FLAG_LEAK
    • CPR_DEBUG_SANITIZER_FLAG_UB
    • CPR_DEBUG_SANITIZER_FLAG_ALL

    What's Changed

    • Replaced build types with flags by @rumgot in https://github.com/libcpr/cpr/pull/853

    Full Changelog: https://github.com/libcpr/cpr/compare/1.9.2...1.9.3

    Source code(tar.gz)
    Source code(zip)
  • 1.9.2(Sep 3, 2022)

    What's Changed

    • Fixed thread pool not creating enough new threads by @COM8 in https://github.com/libcpr/cpr/pull/802
    • Add std::map based constructors to Proxies and ProxyAuthentication by @kp-cat in https://github.com/libcpr/cpr/pull/814

    Full Changelog: https://github.com/libcpr/cpr/compare/1.9.1...1.9.2

    Source code(tar.gz)
    Source code(zip)
  • 1.9.1(Jul 31, 2022)

  • 1.9.0(Jul 18, 2022)

    This will be the last release where the minimum required C++ standard is cpp11. With the next major release (1.10.0) in ~late 2022/early 2023 we will increase the minimum C++ standard to cpp17 (Issue). This release (1.9.0) will still receive bug fixes, at least until the end of 2023, but all new features require from now on a cpp17 compatible compiler.

    Thanks to everyone who helped making this next release of cpr possible 🎉! Especially I would like to thank @simon-berger, @saendigPhilip @leviliangtw .

    In case everything goes like planed we will even offer a .deb package and a NuGet package soon. So stay tuned!

    What's Changed

    • Improve usability for ResponseStringReserve by @WorkingRobot in https://github.com/libcpr/cpr/pull/726
    • Make sure mutex is properly initialized by @cordbleibaum in https://github.com/libcpr/cpr/pull/728
    • Only use CURLOPT_SSLKEY_BLOB on curl 7.71.0+ by @alebcay in https://github.com/libcpr/cpr/pull/737
    • Unified basic, digest and ntlm authentication into one authenticaton class by @simon-berger in https://github.com/libcpr/cpr/pull/735
    • Use UpdateHeader to allow header updates from different sources by @simon-berger in https://github.com/libcpr/cpr/pull/738
    • Added function to get the full request URL by @simon-berger in https://github.com/libcpr/cpr/pull/741
    • Improved range requests and added support for multiple ranges by @simon-berger in https://github.com/libcpr/cpr/pull/742
    • Use thread pool to instead of std::async (#633) by @ithewei in https://github.com/libcpr/cpr/pull/734
    • Add Interceptors by @simon-berger in https://github.com/libcpr/cpr/pull/744
    • Support for CURLOPT_LOCALPORT and CURLOPT_LOCALPORTRANGE by @jmhersc in https://github.com/libcpr/cpr/pull/748
    • Add CaBuffer to enable loading of CA certificates from buffers by @simon-berger in https://github.com/libcpr/cpr/pull/750
    • Add method SetAcceptEncoding for customized Accept-Encoding header (#683) by @leviliangtw in https://github.com/libcpr/cpr/pull/746
    • Add support of customized filename for Multipart (#642) by @leviliangtw in https://github.com/libcpr/cpr/pull/755
    • Added CI script for automatically building a debian package by @saendigPhilip in https://github.com/libcpr/cpr/pull/760
    • Add unit tests for file uploading using buffer of rvalue/lvalue reference (#216) by @leviliangtw in https://github.com/libcpr/cpr/pull/764
    • Add async methods to the Session object interface by @simon-berger in https://github.com/libcpr/cpr/pull/756
    • Add support of file and buffer for the POST Body (#581) by @leviliangtw in https://github.com/libcpr/cpr/pull/763
    • Securely remove sensitive data from memory by @Garfield96 in https://github.com/libcpr/cpr/pull/776
    • secureStringClear Fix for Empty Strings by @COM8 in https://github.com/libcpr/cpr/pull/779
    • New certificates for HTTPS tests by @saendigPhilip in https://github.com/libcpr/cpr/pull/773
    • MacOS and Windows OpenSSL CI fixes by @COM8 in https://github.com/libcpr/cpr/pull/783
    • Refactor cpr::Cookies for storing more fields (#777) by @leviliangtw in https://github.com/libcpr/cpr/pull/778
    • Fix certificate information extraction from the response (#769) by @leviliangtw in https://github.com/libcpr/cpr/pull/781
    • Workaround for PUT requests with a read callback by @COM8 in https://github.com/libcpr/cpr/pull/787

    New Contributors

    • @WorkingRobot made their first contribution in https://github.com/libcpr/cpr/pull/726
    • @cordbleibaum made their first contribution in https://github.com/libcpr/cpr/pull/728
    • @alebcay made their first contribution in https://github.com/libcpr/cpr/pull/737
    • @simon-berger made their first contribution in https://github.com/libcpr/cpr/pull/735
    • @ithewei made their first contribution in https://github.com/libcpr/cpr/pull/734
    • @jmhersc made their first contribution in https://github.com/libcpr/cpr/pull/748
    • @leviliangtw made their first contribution in https://github.com/libcpr/cpr/pull/746
    • @saendigPhilip made their first contribution in https://github.com/libcpr/cpr/pull/760

    Full Changelog: https://github.com/libcpr/cpr/compare/1.8.4...1.9.0

    Source code(tar.gz)
    Source code(zip)
  • 1.8.4(Jul 6, 2022)

    This release addresses a security concern, where an attacker could extract sensitive information from cpr after the application had been exited.

    Changes:

    • Explicit removal of sensitive data from memory (@Garfield96)

    Full Changelog: https://github.com/libcpr/cpr/compare/1.8.3...1.8.4

    Source code(tar.gz)
    Source code(zip)
  • 1.8.3(May 5, 2022)

    This release disables setting SSL-Key blobs for older versions of curl below 7.71.0, since it was not available previously to that. More information on that can be found here: https://github.com/libcpr/cpr/issues/732

    Full Changelog: https://github.com/libcpr/cpr/compare/1.8.2...1.8.3

    Source code(tar.gz)
    Source code(zip)
  • 1.8.2(Apr 27, 2022)

    What's Changed

    • Downgraded curl to 1.80.0 to fix #709 and #732 by @COM8 in https://github.com/libcpr/cpr/pull/733

    Full Changelog: https://github.com/libcpr/cpr/compare/1.8.1...1.8.2

    Source code(tar.gz)
    Source code(zip)
  • 1.8.1(Mar 25, 2022)

  • 1.8.0(Mar 25, 2022)

    Changes

    • Added DownloadAsync(...) #696
    • Added basic range support via SetRange(...) #701
    • Added support for setting the private key blob directly #699
    • Added Mbed TLS support #714
    • Added an option to reserve space before downloading the response string #712
    • Updated the build in curl to 7.81.0
    • Fixed CA-Path for Android #707
    • Fix overwriting of ca bundle #717
    • Fix build with OpenSSL on Ubuntu bionic #696
    • Fixed installing DLLs to binary directory
    Source code(tar.gz)
    Source code(zip)
  • 1.7.2(Dec 9, 2021)

  • 1.7.1(Dec 9, 2021)

    Small bug fix release.

    Changes

    • Fixed setting headers when calling cpr::Session::Download(...).

    Now something like this should work:

    cpr::Url url{server->GetBaseUrl() + "/download_gzip.html"};
    cpr::Session session;
    session.SetUrl(url);
    session.SetHeader(cpr::Header{{"Accept-Encoding", "gzip"}}); // Works now
    cpr::Response response = session.Download(cpr::WriteCallback{write_data, 0});
    
    Source code(tar.gz)
    Source code(zip)
  • 1.7.0(Nov 24, 2021)

    • Added a Cppcheck CI run
    • Fixed automated libcurl ca path detection
    • Fixed missing raw_header in cpr::Response
    • Fixed bugprone narrowing conversions
    • Fixed MaxRedirects exceeded should be treated as error
    • Updated libcurl from 7.75.0 to 7.79.1
    • Fixed cprConfig.cmake when building cpr as a submodule
    • Added cpr version macros in cprver.h
    • Fixed CMake paths for subprojects
    • Updated zlib-ng from 2.0.0-RC2 to 2.0.5
    • Fixed usage of CPR_USE_SYSTEM_GTEST
    • Added CMake find-package support
    • Added more redirect options:
      • cont_send_cred: Continue to send authentication (user+password) credentials when following locations, even when hostname changed.
    • Added an option to specify the HTML version with SetHttpVersion(...)
    • Fixed respecting system proxy configuration
    • Added an option to select the outgoing interface with SetInterface(...)
    • Added an option to get the file download length GetDownloadFileLength(...)
    • Updated Google Tests from 1.10.0 to 1.11.0
    • Added proxy authentication
    • Don't forcibly override user setting for FETCHCONTENT_QUIET
    Source code(tar.gz)
    Source code(zip)
  • 1.6.2(Apr 27, 2021)

  • 1.6.1(Apr 27, 2021)

    Minor feature and bugfix release with the following changes:

    • Added MacOS darwin-ssl support #549
    • Added an option to split a request preparation from its execution #533
    • cpr::Session is now movable #544
    • Not overriding BUILD_TESTING as cache variable any more #561
    • Avoid recursive template instantiation in priv::set_option() #540
    • Do not move targets in to a bin if cpr is a sub project #531
    Source code(tar.gz)
    Source code(zip)
  • 1.6.0(Mar 19, 2021)

    In this release the CMake integration has been refactored to fix a bunch of SSL issues. During this change all relevant CMake variable names changed. Here are the new ones:

    -- =======================================================
    --   CPR_GENERATE_COVERAGE: OFF
    --   CPR_CURL_NOSIGNAL: OFF
    --   CPR_USE_SYSTEM_GTEST: OFF
    --   CPR_FORCE_USE_SYSTEM_CURL: OFF
    --   CPR_ENABLE_SSL: ON
    --   CPR_FORCE_OPENSSL_BACKEND: OFF
    --   CPR_FORCE_WINSSL_BACKEND: OFF
    --   CPR_BUILD_TESTS: ON
    --   CPR_BUILD_TESTS_SSL: ON
    -- =======================================================
    

    Documentation for those can be found here: https://github.com/whoshuu/cpr/blob/aac5058a15e9ad5ad393973dc6fe44d7614a7f55/CMakeLists.txt#L30-L40

    If neither CPR_FORCE_OPENSSL_BACKEND nore CPR_FORCE_WINSSL_BACKEND has been set to ON, CMake will try to automatically detect the best SSL backend for your system (WinSSL - Windows, OpenSSL - Linux & Mac, ...).

    How to build on Windows

    With WinSSL

    mkdir build
    cd build
    cmake .. -DCPR_BUILD_TESTS_SSL=OFF # SSL test are only supported with OpenSSL
    cmake --build .
    

    With OpenSSL

    mkdir build
    cd build
    cmake .. -DCPR_FORCE_OPENSSL_BACKEND=ON # Disable auto detect and force OpenSSL
    cmake --build .
    

    Changes

    • Added support for GCC10 static analysis
    • Added an option to retrieve the std::shared_ptr<CurlHolder> from a session
    • Added UpdateHeader(const Header& header) support #506
    • Added support for retrieving certificate information #453
    • Added urlDecode(std::string) for url decoding
    • Add BearerToken support #465
    • Explicit move operator for StringHolder
    • cpr::Session cleanup and allow the compiler to generate the needed constructor
    • Updated curl from 7.69.1 to 7.75.0 #529
    • Compatibility for libcurl <= 7.60
    • Less auto and more explicit types
    • Refactored the CMake variables #529
    • Change listening ports used for tests
    • Fixed AbstractServer data race
    • Fixed Windows OpenSSL builds #529
    • Fixed Windows SSL backend detection #529
    • Fixed ReadCallback will reset Header #517
    • Fixed the Windows OpenSSL CI build
    Source code(tar.gz)
    Source code(zip)
  • 1.5.2(Oct 20, 2020)

    This hotfix for v1.5.1 includes the following fixes:

    • Fixed: cpr::Post wrong content length (#450, #456, #458)
    • Fixed: Mutex for multithreaded access not being static
    • Fixed: No const rvalue references (#424)
    Source code(tar.gz)
    Source code(zip)
  • v1.5.1(Jul 8, 2020)

    Changes

    • CMake add ability to use WINSSL (#404)
    • Thread save access to libCurl (#313)
    • Allow implicit creation of cpr:Url, cpr:Body and cpr:UserAgent (#411)
    • Payload with string variables (#409)
    • Cleanup (#407, #408)
    Source code(tar.gz)
    Source code(zip)
  • 1.5.0(Jun 22, 2020)

    Changes

    • Updated CURL to curl-7_69_1 (#343)
    • Updated mongoose to 6.18
    • Updated googletest to release-1.10.0
    • Refactored the mongoose test server setup
    • Added SSL options (#276)
    • Fixed URL encoding (#379)
    • Fixed Windows std::min type deduction
    • GitHub Actions CI (#393)
    • Refactored all the CMake stuff (#383)
    • Fixed passing correct data type when setting CURLOPT_POSTFIELDSIZE_LARGE
    • Switched Body, UserAgent and Url from std::string derivation classes to string holder classes (#303)
    • General cleanup of the code base
    Source code(tar.gz)
    Source code(zip)
Owner
C++ Requests: Curl for People, a spiritual port of Python Requests.
null
JeVois-Pro People Counter : Implement people counter on JeVois-Pro Deep Learning Smart Camera

JeVois-Pro People Counter Refer to the OpenCV People Counter article to implement a people counter on the JeVois-Pro Deep Learning Smart Camera. First

On-Device AI Co., Ltd. 1 Nov 10, 2021
This is a simple version of Apex-Legends-SDK since so many people having struggles with python binding

This is a simple version of Apex-Legends-SDK since so many people having struggles with python binding

skidword64 42 Nov 3, 2022
Threat Emulation and Red Teaming Framework, The Hacking Software for normal people.

The Remote Hacker Probe is a Threat Emulation and Red Teaming Framework built to be easy to use. The Remote Hacker Probe is Feature Rich! Including, K

QuantumCored 176 Nov 27, 2022
A simple wrapper for 'pacman' with a syntax similar to 'apt' to help people transitioning to Arch and Arch based distributions like Manjaro.

aptpac aptpac is a program which helps with the transition to Arch Linux and Arch based distros like Manjaro. It simplifies using pacman as it works l

Itai Nelken 17 Sep 26, 2022
Off The Grid (OTG) Messenger is an easy way for people to communicate through text messages when in remote areas.

Off The Grid (OTG) Messenger is an easy way for people to communicate through text messages when in remote areas. With a theoretical transmission range of 10 miles (16kms), OTG messenger can be used by groups of people to stay connected when they are in areas not serviced by mobile connectivity.

Trevor Attema 491 Sep 15, 2022
The Xnoe Operating System, for people who want an OS that is useless.

Xnoe OS An attempt at writing an "Operating System" in x86 assembler. Hi all, I have many hobbies, one of those is torturing myself with knowledge I p

Xnoe 10 Oct 7, 2022
To turn on and off the pump, most people use a manual switch.

To turn on and off the pump, most people use a manual switch. As a result, people forget to switch off the pump from time to time, resulting in water overflow. They may forget to switch on the motor at times, resulting in a water problem later on. It also wastes a lot of electricity. To solve this problem, we need a smart device to control the pump.

Md. Asad Chowdhury Dipu 1 Aug 20, 2022
ClickLock which supports old games where the Windows ClickLock fails to work. This is a charity project, designed for people with disabilities.

Mouse ClickLock For Games This small utility works in a similar way as ClickLock available on Windows, but also supports old games where the normal Cl

null 7 Oct 8, 2022
🔍 A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.

?? ImHex A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM. Supporting If you like my work, plea

WerWolv 22.6k Nov 27, 2022
A repo for helping people get started with Competitive Programming and Data Structures & Algorithms

Hack CP DSA Update regarding hacktoberfest: please refer this announcement Wanna improve your problem solving skills ❓ Wanna practice collaborating on

TLE MEC 174 Nov 5, 2022
Remote hacker probe - Threat Emulation and Red Teaming Framework, The Hacking Software for normal people.

The Remote Hacker Probe is a Threat Emulation and Red Teaming Framework built to be easy to use. The Remote Hacker Probe is Feature Rich! Including, K

Fahad 176 Nov 27, 2022
Software to support people learning OpenMP with our book

Software to support people learning OpenMP with our book ... The OpenMP Common Core: Making OpenMP Simple Again

Tim Mattson 50 Nov 18, 2022
Bank of challenges & solutions from r/dailyprogrammer for people learning to program

DailyProgrammerChallenges This repo contains all of the challenges from r/dailyprogrammer and also scripts used to pull challenges from the subreddit

Freddie Vargus 316 Aug 24, 2022
An Xposed module to detect or reject applist requests

Hide My Applist About this module Although "It is incorrect to detect specific app's installation", yet not every app using root provides random packa

null 1.1k Nov 27, 2022
Register for Hacktoberfest and make four pull requests (PRs) between October 1st-31st to grab free SWAGS

⭐️ Projects and Codes ⭐️ This is beginner friendly repo. We aim for beginners to start with their first contributions to open-source. If you are looki

Joel Sunny Varghese 8 Oct 14, 2022
You may learn how to make successful pull requests and get your first valid open source contribution by using this repository.

Your-First-Contribution You may learn how to make successful pull requests and get your first valid open source contribution by using this repository.

Veshraj Ghimire 24 Aug 23, 2022
Helping everyone to code and creating pull requests

Novice Coding It's an initiative to help create more awareness about Open Source and help introduce many more students to the benefits of FOSS. We wil

Saptarshi Sarkar 19 Oct 15, 2022
all valid pull requests accepted!!

Hacktoberfest_2021 Hacktober Fest Details Important Notice The repository has been marked as "Excluded Project" by Hacktoberfest Algorithm. I have no

Gautam Jain 23 Aug 6, 2022
Lua HTTP async client using libcurl (supports multi requests in parallel)

lua-async-http lua-async-http rock, is a new lua rock written in C and based on libcurl. It allow us to make multiple http/https (with client certific

International Business Machines 5 Oct 25, 2022