Home > other >  How to store sent/received data with libcurl
How to store sent/received data with libcurl

Time:10-26

Im trying to implement some curl and curlcpp functions for a small project.

So far i have implemented a few functions but now i want to add functionality. The idea is to store in a buffer the sent and receive data so later i can access:

  • Sent Data
  • Sent Headers
  • Received Data
  • Received Headers

I know there is CURLOPT_WRITEFUNCTION but this only works for response data and i need the output data/headers too. CURLOPT_DEBUGFUNCTION looks that works for me but i cant configure it on CPP.

Here is an example code of my class:

class CurlCPPClient
{
    private:
        ...
        int trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr);
        curl::curl_easy curl_easy;
        std::string raw_data;
    public:
        ...
}

CurlCPPClient::CurlCPPClient()
{
    curl_easy.add<CURLOPT_DEBUGFUNCTION>(this->trace_data);
}

int CurlCPPClient::trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr) 
{
  std::string frame_info(data);

  switch(type)
  {
    case CURLINFO_HEADER_OUT:
    case CURLINFO_DATA_OUT:
      raw_data  = frame_info;
      break;
    case CURLINFO_HEADER_IN:
    case CURLINFO_DATA_IN:
      raw_data  = frame_info;
      break;
    default:
      break;
  }

  return 0;
}

I have compiler issues when setting the function pointer to trace_data. I get "error C3867" and "error C2228" with: this->trace_data, this.trace_data, trace_data. If i dont use trace_data as a method of my class, i can call it but i cant save the info on a member to access it later in another part of the class.

CodePudding user response:

libcurl expects standalone C-style functions for its callbacks. You can't use a non-static class method for a callback.

Declare your trace_data() method as static. You can use CURLOPT_DEBUGDATA to pass the this pointer of the CurlCPPClient object to the method's userptr parameter.

class CurlCPPClient
{
    private:
        ...
        static int trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr);
        curl::curl_easy curl_easy;
        std::string raw_data;
    public:
        ...
}

CurlCPPClient::CurlCPPClient()
{
    curl_easy.add<CURLOPT_DEBUGFUNCTION>(&CurlCPPClient::trace_data);
    curl_easy.add<CURLOPT_DEBUGDATA>(this);
}

int CurlCPPClient::trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr) 
{
  CurlCPPClient *pThis = static_cast<CurlCPPClient*>(userptr);
  std::string frame_info(data, size);

  switch(type)
  {
    case CURLINFO_HEADER_OUT:
    case CURLINFO_DATA_OUT:
      pThis->raw_data  = frame_info;
      break;
    case CURLINFO_HEADER_IN:
    case CURLINFO_DATA_IN:
      pThis->raw_data  = frame_info;
      break;
    default:
      break;
  }

  return 0;
}

Alternatively, use CURLOPT_DEBUGDATA to pass just the raw_data member to the callback:

class CurlCPPClient
{
    private:
        ...
        static int trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr);
        curl::curl_easy curl_easy;
        std::string raw_data;
    public:
        ...
}

CurlCPPClient::CurlCPPClient()
{
    curl_easy.add<CURLOPT_DEBUGFUNCTION>(&CurlCPPClient::trace_data);
    curl_easy.add<CURLOPT_DEBUGDATA>(&raw_data);
}

int CurlCPPClient::trace_data(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr) 
{
  std::string *pRawData = static_cast<std::string*>(userptr);
  std::string frame_info(data, size);

  switch(type)
  {
    case CURLINFO_HEADER_OUT:
    case CURLINFO_DATA_OUT:
      *pRawData  = frame_info;
      break;
    case CURLINFO_HEADER_IN:
    case CURLINFO_DATA_IN:
      *pRawData  = frame_info;
      break;
    default:
      break;
  }

  return 0;
}
  • Related