Curl命令行有效,C++Curl库无效

Curl command line works, C++ curl library does not

本文关键字:无效 C++Curl 命令行 有效 Curl      更新时间:2023-10-16

我正试图通过C++的curl库进行一些请求。我可以成功地完成我的请求,并通过命令行获得正确的响应,但我无法通过C++代码得到正确的响应。我的命令行命令看起来像这个

curl -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -H 'Authorization: <some_hash_value>' -k <my_full_url> -data '<my_json_string>'

这很好。现在我尝试在C++代码中执行同样的请求。我的代码看起来像这个

void performRequest(const std::string& json, const void* userData, CallbackFunction callback)
{
    struct curl_slist* headers = NULL;
    headers = curl_slist_append(headers, "Accept: application/json");
    headers = curl_slist_append(headers, "Content-Type: application/json");
    headers = curl_slist_append(headers, (std::string("Authorization: ") + m_authorization).c_str());
    CURL* curlHandle = curl_easy_init();
    if (!curlHandle)
    {
        std::cerr << "Curl handler initialization failed";
    }
    curl_easy_setopt(curlHandle, CURLOPT_NOSIGNAL, 1);
    curl_easy_setopt(curlHandle, CURLOPT_HTTPHEADER, headers);
    // specify target URL, and note that this URL should include a file name, not only a directory
     curl_easy_setopt(curlHandle, CURLOPT_URL, m_url.c_str());
    // enable uploading
    curl_easy_setopt(curlHandle, CURLOPT_UPLOAD, 1L);
    // set HTTP method to POST
    curl_easy_setopt(curlHandle, CURLOPT_CUSTOMREQUEST, "POST");
    // set json data; I use EXACTLY the same string as in command line
    curl_easy_setopt(curlHandle, CURLOPT_COPYPOSTFIELDS, json.c_str());
    // set data size
    curl_easy_setopt(curlHandle, CURLOPT_POSTFIELDSIZE_LARGE, json.size());
    // set user data for getting it in response
    curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, userData);    // pointer to a custom struct
    // set callback function for getting response
    curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, callback);    // some callback
    // send request
    curl_easy_perform(curlHandle);
    curl_easy_cleanup(curlHandle);
    curl_slist_free_all(headers);
}

然而,由于某种原因,我在来自服务器的响应中收到了一个错误,从中我可以假设我的代码的请求与命令行的命令不等价。尸体似乎没有被送来。当我使用CURLOPT_DEBUGFUNCTION转储调试信息时,我看不到我的请求Json主体。

这里有什么问题?我做错了什么?有什么想法吗?

以下是适用于您的示例代码。

注意我:

  • 删除了CURLOPT_UPLOAD,因为看起来并不是在上传什么,而是在做一个简单的POST

  • CURLOPT_CUSTOMREQUEST更改为CURLOPT_POST(这并不重要),但我发现它更干净。

  • 重新排序的CURLOPT_POSTFIELDSIZE_LARGECURLOPT_COPYPOSTFIELDS

  • 为了这个示例代码,删除了CURLOPT_WRITEDATA行。

我只通过连接到nc -l localhost 80 的实例测试了以下内容

 static size_t callback(char *ptr, size_t size, size_t nmemb, void *userdata)
 {
   string s(ptr);
   cout << s << endl;
   return size * nmemb;
 }

 int main(int argc, char** argv)
 {
   string m_authorization("PWNED");
   string m_url("http://localhost");
   string m_json("{}");
   curl_global_init(CURL_GLOBAL_ALL);
   CURL* curlHandle = curl_easy_init();
   struct curl_slist* headers = nullptr;
   headers = curl_slist_append(headers, "Accept: application/json");
   headers = curl_slist_append(headers, "Content-Type: application/json");
   headers = curl_slist_append(headers, (std::string("Authorization: ") + m_authorization).c_str());
   curl_easy_setopt(curlHandle, CURLOPT_NOSIGNAL, 1);
   curl_easy_setopt(curlHandle, CURLOPT_HTTPHEADER, headers);
   // specify target URL, and note that this URL should include a file name, not only a directory
   curl_easy_setopt(curlHandle, CURLOPT_URL, m_url.c_str());
   // <= You are not uploading anything actually, this is a simple POST with payload
   // enable uploading
   // curl_easy_setopt(curlHandle, CURLOPT_UPLOAD, 1L);
   // set HTTP method to POST
   curl_easy_setopt(curlHandle, CURLOPT_POST, 1L);
   // set data size before copy
   curl_easy_setopt(curlHandle, CURLOPT_POSTFIELDSIZE_LARGE, m_json.size());
   // set json data; I use EXACTLY the same string as in command line
   curl_easy_setopt(curlHandle, CURLOPT_COPYPOSTFIELDS, m_json.c_str());
   // set user data for getting it in response
   // curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, userData);    // pointer to a custom struct
   // set callback function for getting response
   curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, callback);    // some callback
   // send request
   curl_easy_perform(curlHandle);
   curl_slist_free_all(headers);
   curl_easy_cleanup(curlHandle);
   curl_global_cleanup();
   return 0;
 }

在windows中,您必须使用以下函数初始化winsock内容

curl_global_init(CURL_GLOBAL_ALL);

根据Rocki和drew010的意见,问题得到了解决。

  1. 我已经删除了CURLOPT_CUSTOMREQUESTCURLOPT_UPLOADCURLOPT_NOSIGNAL设置语句,因为不需要它们
  2. 我还删除了用于设置CURLOPT_POSTFIELDSIZE_LARGE的行,尽管如果它是在设置CURLOPT_COPYPOSTFIELDS之前设置的,它也可以正常工作。如果在CURLOPT_COPYPOSTFIELDS之前没有设置大小,则假设数据是以零结尾的字符串;否则,存储的大小会通知库要复制的字节计数。在任何情况下,除非发出另一个CURLOPT_POSTFIELDSCURLOPT_COPYPOSTFIELDS选项,否则不得在CURLOPT_COPYPOSTFIELDS之后更改大小。(请参阅:curl.haxx.se/libcurl/c/CURLOPT_COPYPOSTFIELDS.html)