Как отобразить PUT curl в CPP Curlpp? - PullRequest
0 голосов
/ 11 октября 2019

Я хотел бы отобразить / написать ниже curl (этот curl работает правильно в терминале Linux) в код cpp:

curl -X PUT -u "abc" \
    "https://api123.pl" \
    -d 'symbol=EB&side=ri&quantity=3'

Ниже приведен код CPP с использованием библиотеки Curlpp:

    #include <iostream>
    #include <sstream>
    #include <curlpp/cURLpp.hpp>
    #include <curlpp/Easy.hpp>
    #include <curlpp/Options.hpp>
    using namespace curlpp::options;
    using namespace std;
    /*
    curl -X PUT -u "abc" \
        "https://api123.pl" \
        -d 'symbol=EB&side=ri&quantity=3'
    g++ name1.cpp -lcurl -lcurlpp -o name1 && ./name1
    */
    string test(const std::string &url) {
        try {
            curlpp::Cleanup cleanup;
            curlpp::Easy request;
            request.setOpt<curlpp::Options::Url>(url);
            request.setOpt(new curlpp::options::UserPwd("abc"));
            request.setOpt(new curlpp::options::CustomRequest{"PUT"});
//    /*
    //does not compile
            std::list<std::string> postContent;
            postContent.push_back("symbol:EB");
            postContent.push_back("side:ri");
            postContent.push_back("quantity:3");
            request.setOpt(new curlpp::options::PostFields(postContent));
//    */     
            std:stringstream content;
            content << request;        
            return content.str().c_str();
        }
        catch (const curlpp::RuntimeError &e) {
            std::cout << "CURLpp runtime error: " << e.what() << std::endl;
        }
        catch (const curlpp::LogicError &e) {
            std::cout << "CURLpp logic error: " << e.what() << std::endl;
        }
        throw std::string("Error");
    }
    int main(int, char **) {
        try {
            cout << test("https://api123.pl");
        }
        catch(curlpp::RuntimeError & e) {
            std::cout << e.what() << std::endl;
        }
        catch(curlpp::LogicError & e)   {
            std::cout << e.what() << std::endl;
        }
        return 0;
    }

У меня ошибка при компиляции:

1.2putStackoverflow.cpp: In function ‘std::string getJSONAPIResultFromURL(const string&)’:
1.2putStackoverflow.cpp:31:67: error: no matching function for call to ‘curlpp::OptionTrait<std::__cxx11::basic_string<char>, CURLOPT_POSTFIELDS>::OptionTrait(std::__cxx11::list<std::__cxx11::basic_string<char> >&)’
   31 |         request.setOpt(new curlpp::options::PostFields(postContent));
      |                                                                   ^
In file included from /usr/include/curlpp/Option.hpp:251,
                 from /usr/include/curlpp/Easy.hpp:31,
                 from 1.2putStackoverflow.cpp:4:
/usr/include/curlpp/Option.inl:129:1: note: candidate: ‘curlpp::OptionTrait<OptionType, opt>::OptionTrait() [with OptionType = std::__cxx11::basic_string<char>; CURLoption opt = CURLOPT_POSTFIELDS]’
  129 | OptionTrait<OptionType, option>::OptionTrait()
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/curlpp/Option.inl:129:1: note:   candidate expects 0 arguments, 1 provided
/usr/include/curlpp/Option.inl:123:1: note: candidate: ‘curlpp::OptionTrait<OptionType, opt>::OptionTrait(typename curlpp::Option<OptionType>::ParamType) [with OptionType = std::__cxx11::basic_string<char>; CURLoption opt = CURLOPT_POSTFIELDS; typename curlpp::Option<OptionType>::ParamType = const std::__cxx11::basic_string<char>&]’
  123 | OptionTrait<OptionType, option>::OptionTrait(typename Option<OptionType>::ParamType value)
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/curlpp/Option.inl:123:85: note:   no known conversion for argument 1 from ‘std::__cxx11::list<std::__cxx11::basic_string<char> >’ to ‘curlpp::Option<std::__cxx11::basic_string<char> >::ParamType’ {aka ‘const std::__cxx11::basic_string<char>&’}
  123 | OptionTrait<OptionType, option>::OptionTrait(typename Option<OptionType>::ParamType value)
      |                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
In file included from /usr/include/curlpp/Easy.hpp:31,
                 from 1.2putStackoverflow.cpp:4:
/usr/include/curlpp/Option.hpp:145:8: note: candidate: ‘curlpp::OptionTrait<std::__cxx11::basic_string<char>, CURLOPT_POSTFIELDS>::OptionTrait(const curlpp::OptionTrait<std::__cxx11::basic_string<char>, CURLOPT_POSTFIELDS>&)’
  145 |  class OptionTrait : public Option<OptionType>
      |        ^~~~~~~~~~~
/usr/include/curlpp/Option.hpp:145:8: note:   no known conversion for argument 1 from ‘std::__cxx11::list<std::__cxx11::basic_string<char> >’ to ‘const curlpp::OptionTrait<std::__cxx11::basic_string<char>, CURLOPT_POSTFIELDS>&’
/usr/include/curlpp/Option.hpp:145:8: note: candidate: ‘curlpp::OptionTrait<std::__cxx11::basic_string<char>, CURLOPT_POSTFIELDS>::OptionTrait(curlpp::OptionTrait<std::__cxx11::basic_string<char>, CURLOPT_POSTFIELDS>&&)’
/usr/include/curlpp/Option.hpp:145:8: note:   no known conversion for argument 1 from ‘std::__cxx11::list<std::__cxx11::basic_string<char> >’ to ‘curlpp::OptionTrait<std::__cxx11::basic_string<char>, CURLOPT_POSTFIELDS>&&’

Проблема с:

        std::list<std::string> postContent;
        postContent.push_back("symbol:EB");
        postContent.push_back("side:ri");
        postContent.push_back("quantity:3");
        request.setOpt(new curlpp::options::PostFields(postContent));

Для компиляции программы:

g++ name1.cpp -lcurl -lcurlpp -o name1 && ./name1

Я не знаю какнаписать код для отображения / записи curl в cpp с помощью curlpp. Спасибо за помощь.

1 Ответ

1 голос
/ 11 октября 2019

PostFields - это просто typedef для cURLpp::OptionTrait<std::string, cURL::CURLOPT_POSTFIELDS>, ниже я упрощаю.

Если вы внимательно прочитаете сообщения об ошибках, они точно скажут, чтонеправильный:

ошибка: не найдена соответствующая функция для вызова curlpp :: OptionTrait:: OptionTrait (станд :: __ cxx11 :: Список&) '

В сущности, это означает, что вы не можете передать std::list<std::string> в конструктор PostFields. В подробностях ошибки сообщается о 4 возможных конструкторах, ни один из которых не принимает std::list в качестве ввода:

PostFields()
PostFields(const std::string&)
PostFields(const PostFields&)
PostFields(PostFields&&)

Действительно, если вы прочитаете документацию cURLpp , вы не сможетесоздать PostFields из std::list. Что имеет смысл, согласно документации cURL для CURLOPT_POSTFIELDS:

Передать символ * в качестве параметра, указывая на полные данные для отправкив операции HTTP POST. Вы должны убедиться, что данные отформатированы так, как вы хотите, чтобы сервер их получал. libcurl не будет преобразовывать или кодировать его для вас в любом случае. Например, веб-сервер может предполагать, что эти данные имеют URL-кодировку.

CURLOPT_POSTFIELDS ожидает один char* в качестве ввода (который cURLpp переносит с использованием std::string), поэтому вы должны передать данные PUT в виде одной строки в кодировке URL, каквы делаете в командной строке, например:

request.setOpt(new curlpp::Options::PostFields("symbol=EB&side=ri&quantity=3"));

Откуда у вас появилась идея, что вы можете использовать std::list с PostFields?


BTW, в соответствии сдокументация cURLpp, вам не нужно использовать new при добавлении параметров к объекту curlpp::Easy:

curlpp::Easy request;
request.setOpt(curlpp::Options::Url(url));
request.setOpt(curlpp::Options::UserPwd("abc"));
request.setOpt(curlpp::Options::CustomRequest("PUT"));
request.setOpt(curlpp::Options::PostFields("symbol=EB&side=ri&quantity=3"));
...