C ++ libcurl没有发布数据

时间:2018-02-04 20:20:09

标签: c++ curl

我正在开发一个C ++库,它利用curl库对Web服务执行HTTP POST请求。

我有一个负责执行curl和处理响应的函数,这个函数调用另一个函数来设置curl,因为它可以在多个地方使用相同的设置。

它成功连接到Web服务,但我可以看到返回的响应,但是没有发布到Web服务的帖子数据。

在我必须执行HTTP请求的代码下面。

第一个函数是执行curl执行的函数,它调用一个函数来初始化curl库,然后将指针返回给它以供使用。

string response;
struct curl_slist *list = NULL;
const char * jsonString = ddEvent.getDDEventAsJSONString().c_str();
CURL *curl = this->initCurl(ddEvent, &response, list, &jsonString);
if (curl == NULL)
{
    return false;
}

list = curl_slist_append(list, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
CURLcode res = curl_easy_perform(curl);

初始化curl的函数如下:

CURL * MyClass::initCurl(DDEvent ddEvent, string *response, struct curl_slist *list, const char **jsonString)
{
    CURL *curl = NULL;

    curl = curl_easy_init();
    if (curl == NULL)
    {
        cout << "Failed to initialise curl" << endl;
        return NULL;
    }
    stringstream url_stream;
    url_stream << "http://192.168.1.123";
    string url= dd_url_stream.str();

    cout << "Using URL: " << url<< endl;

    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &MyClass::curlResponseWriteCallback);
    curl_easy_setopt(curl, CURLOPT_HEADER, 1);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, *jsonString);

    return curl;
}

此外,帖子数据是一个JSON字符串,它不是一个键/值发布表单数据。

以下是curl的详细模式的输出

Using JSON string {"title":"HTTP Event Teesg","text":"Test warning event","alert_type":"success","tags":["simple_string_tag"]}
Using URL: http://192.168.1.123
* About to connect() to 192.168.1.123 port 80 (#0)
*   Trying 192.168.1.123...
* Connected to 192.168.1.123 (192.168.1.123) port 80 (#0)
> POST / HTTP/1.1
Host: 192.168.1.123
Accept: */*
Content-Type: application/json
Content-Length: 0

< HTTP/1.1 200 OK
< Date: Sun, 04 Feb 2018 20:11:12 GMT
< Server: Apache/2.4.6 (CentOS) PHP/5.6.32
< X-Powered-By: PHP/5.6.32
< X-XSS-Protection: 1; mode=block
< Content-Length: 52
< Content-Type: text/html; charset=UTF-8
<

2 个答案:

答案 0 :(得分:0)

传出请求中的Content-Length: 0表示您传递给CURLOPT_POSTFIELDS的数据长度为零。

请注意,CURLOPT_POSTFIELDS不会复制数据,它只是指向您的内存,因此您可能希望确保数据在libcurl需要的整个时间内仍然存在。由于您没有向我们展示整个程序,我们无法确切地告诉您这是如何发生的。

最后:为什么不直接将'char *'传递给 initCurl 而不是'char **',你需要在方法中取消引用?这对我来说很奇怪。

答案 1 :(得分:0)

似乎ddEvent.getDDEventAsJSONString()返回一个临时的std :: string对象。 将其保存在本地变量中,然后将其作为引用传递。

std::string jsonString = ddEvent.getDDEventAsJSONString();
this->initCurl(ddEvent, &response, list, jsonString);

CURL * MyClass::initCurl(DDEvent ddEvent, string *response, struct curl_slist *list, const std::string& jsonString)

由于CURLOPT_POSTFIELDS不会将字符串复制到libcurl中,因此必须一直保持字符串活动状态,直到调用curl_easy_perform()为止。

作为“ char *”参数传递给libcurl的字符串由库复制;因此,在curl_easy_setopt返回之后,可能会覆盖与指针参数关联的字符串存储。此规则的唯一例外是CURLOPT_POSTFIELDS,但是复制字符串CURLOPT_COPYPOSTFIELDS的替代方法具有一些使用特性,您需要仔细阅读。

在jsonString的生存范围内调用curl_easy_perform的代码没有问题。但是,如果您打算稍后调用该函数,请使用CURLOPT_COPYPOSTFIELDS代替CURLOPT_POSTFIELDS来复制和存储要发布的数据。