如何使用 libcurl 存储 sent/received 数据

How to store sent/received data with libcurl

我正在尝试为一个小项目实现一些 curl 和 curlcpp 功能。

到目前为止,我已经实现了一些功能,但现在我想添加功能。这个想法是将发送和接收数据存储在缓冲区中,以便稍后我可以访问:

我知道有 CURLOPT_WRITEFUNCTION 但这只适用于响应数据,我也需要输出 data/headers。 CURLOPT_DEBUGFUNCTION 看起来对我有用,但我无法在 CPP 上配置它。

这是我的示例代码 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;
}

我在将函数指针设置为 trace_data 时遇到编译器问题。我得到“错误 C3867”和“错误 C2228”:this->trace_data、this.trace_data、trace_data。 如果我不使用 trace_data 作为我的 class 的方法,我可以调用它,但我无法保存成员的信息以便稍后在 class 的另一部分访问它。

libcurl 的回调需要独立的 C 风格函数。您不能使用 非静态 class 方法 进行回调。

将您的 trace_data() 方法声明为 static。您可以使用 CURLOPT_DEBUGDATACurlCPPClient 对象的 this 指针传递给方法的 userptr 参数。

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;
}

或者,使用 CURLOPT_DEBUGDATA 仅将 raw_data 成员传递给回调:

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;
}