1

I want to write C++ code with using curlpp library which work exactly as following example on curl if it possible of course.

> curl -H "Content-Type: application/json" -X POST -d '{"param1":"val1", "param2":"val2", "param3":"val3"}' --data-binary '@/tmp/somefolder/file.bin' https://my-api.somedomain.com:1024/my_command_url
>

I was able to write transfer json text with method POST but when I added upload command this library substitute PUT instead of POST.

  • `curl` is a command line tool. You need to look at `libcurl` https://curl.haxx.se/libcurl/c/ – Martin York Oct 31 '18 at 20:45
  • I have found following example "HTTP Multipart formpost with file upload and two additional parts." but I'm sure the same ability is in curlpp too... I will try to use it. – Yevgen Taradayko Oct 31 '18 at 21:30
  • 1
    @MartinYork [curlpp](http://www.curlpp.org/) is a C++ wrapper for libcurl (the [Bindings](https://curl.haxx.se/libcurl/bindings.html) page on the libcurl site even links to curlpp). Yevgeny wants to replicate the `curl` command using curlpp. – Remy Lebeau Oct 31 '18 at 21:33
  • @YevgenyTaradayko rather than asking for examples (which is off-topic for StackOverflow), please show what you have tried so far, then someone can point out what is missing or needs to be changed – Remy Lebeau Oct 31 '18 at 21:36
  • I used example 21. I think pointless to post that code here. I think now I should try "Example 19: Multipart/formdata HTTP POST example." – Yevgen Taradayko Oct 31 '18 at 21:42
  • Seems I have found solution. All of I need it's just add file's content after json part after ampersand. So question can be closed. – Yevgen Taradayko Nov 01 '18 at 01:20
  • Tested and confirmed. It works. – Yevgen Taradayko Nov 01 '18 at 02:34

2 Answers2

2

I decided to post answer here, perhaps it will help somebody like me

static string post_request(const string url,const string body1,const string path2file)
{
   const string field_divider="&";
   stringstream result;
   try
   {
      using namespace std;

      // This block responsible for reading in the fastest way media file
      //      and prepare it for sending on API server
      ifstream is(path2file);
      is.seekg(0, ios_base::end);
      size_t size=is.tellg();
      is.seekg(0, ios_base::beg);
      vector<char> v(size/sizeof(char));
      is.read((char*) &v[0], size);
      is.close();
      string body2(v.begin(),v.end());

      // Initialization
      curlpp::Cleanup cleaner;
      curlpp::Easy request;
      list< string > headers;
      headers.push_back("Content-Type: application/json");
      headers.push_back("User-Agent: curl/7.77.7");

      using namespace curlpp::Options;

      request.setOpt(new Verbose(true));
      request.setOpt(new HttpHeader(headers));
      request.setOpt(new Url(url));
      request.setOpt(new PostFields(body1+field_divider+body2));
      request.setOpt(new PostFieldSize(body1.length()+field_divider.length()+body2.length()));
      request.setOpt(new curlpp::options::SslEngineDefault());
      request.setOpt(WriteStream(&result));
      request.perform();
   }
   catch ( curlpp::LogicError & e )
     {
       cout << e.what() << endl;
     }
   catch ( curlpp::RuntimeError & e )
     {
       cout << e.what() << endl;
     }

   return (result.str());

}
2

I tried using the posted answer but found that it did not work well with express' json parser and it would give a bad request each time. I think using curlpp's form data is most likely the best option. See the code below for a basic example of sending a json string and a file in the form:

std::string BasicFormDataPost(std::string url, std::string body1, std::string filename)
{
  std::ostringstream result;
  try
  {
  // Initialization
  curlpp::Cleanup cleaner;
  curlpp::Easy request;
  curlpp::Forms formParts;
  formParts.push_back(new curlpp::FormParts::Content("formjson",body1)); // One has to remember to JSON.parse on the server to use the body data.
  formParts.push_back(new curlpp::FormParts::File("attachment", filename));

  using namespace curlpp::Options;

  // request.setOpt(new Verbose(true));
  request.setOpt(new Url(url));
  request.setOpt(new HttpPost(formParts));
  request.setOpt(WriteStream(&result));
  request.perform();
  return std::string( result.str());  
 }
 catch ( curlpp::LogicError & e )
 {
   std::cout << e.what() << std::endl;
 }
 catch ( curlpp::RuntimeError & e )
 {
   std::cout << e.what() << std::endl;
 }

}

This answer was pieced together from the previous answer and the curlpp examples located at: https://github.com/datacratic/curlpp/tree/master/examples

jman
  • 685
  • 5
  • 15