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