【问题标题】:How to make a libcurl HTTP webrequest?如何制作 libcurl HTTP webrequest?
【发布时间】:2016-07-18 06:00:42
【问题描述】:

我正在尝试从 url 获取 json 数据:

sub.domain.com/rest/getdiscounts?supermarketid=5323

我想获取从该 url 返回的数据。在终端我可以这样做:

curl --user user:password "http://sub.domain.com/rest/getdiscounts?supermarketid=5323"

到目前为止,我已经尝试了多种方法,例如:

static string lastResponse;

size_t server_response_stream(void *ptr, size_t size, size_t nmemb, void *)
{
  lastResponse += (const char*)ptr;
  return size * nmemb;
}

bool get_request(string data1, string& errorDescription)
{
  CURL *curl = curl_easy_init();
  if (curl == NULL)
  {
    errorDescription = "Unable to initialise Curl";
    cout << errorDescription << std::endl;
    return false;
  }
  const string url = "http://sub.domain.com/rest/";
  curl_easy_setopt(curl, CURLOPT_URL, (url + "getdiscounts").c_str());
  curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
  curl_easy_setopt(curl, CURLOPT_USERPWD, USPA);

  char* dc1 = curl_easy_escape(curl, data1.c_str(), 0);
  string arg = "supermarketid=" + (string)dc1;
  const char* dt = arg.c_str();

  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, dt);
  curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(dt));

  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

  lastResponse = "";
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, server_response_stream);

  CURLcode res = curl_easy_perform(curl);

  res = curl_easy_perform(curl);

  if (res != CURLE_OK)
  {
    errorDescription = "Curl call to server failed!";
    cout << errorDescription << std::endl;
    return false;
  }

  curl_easy_cleanup(curl);
  return true;
}

我使用this questionthis link 作为来源。

编辑:感谢您的帮助!我又从头开始了,它现在可以工作了:

static string responseStr;
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *)
{
  responseStr = (const char*)ptr;
  return size * nmemb;
}

string get_request()
{
  CURL *curl;
  CURLcode res;

  curl = curl_easy_init();
  if (curl)
  {
    curl_easy_setopt(curl, CURLOPT_URL, "http://sub.domain.com/rest/getdiscounts?supermarketid=5323");
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_easy_setopt(curl, CURLOPT_USERPWD, CREDENTIALS);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);

    res = curl_easy_perform(curl);

    if (res != CURLE_OK)
    {
      cout << "curl_easy_perform() failed!" << std::endl;
      curl_easy_strerror(res);
      curl_easy_cleanup(curl);
      return "";
    }

    else if (res == CURLE_OK)
    {
      curl_easy_cleanup(curl);
      return responseStr;
    }
  }
}

【问题讨论】:

  • 为什么要调用perform两次?
  • @2501 第一次调用验证第二次调用来完成工作。
  • curl --user user:password "http://sub.domain.com/rest/getdiscounts?supermarketid=5323" 当你构造一个 POST 请求时,这看起来像一个 GET 请求,是不是很奇怪?
  • @Zero 您发布的链接中的文章也有同样的错误。
  • @Zero 在这种情况下,我认为不需要调用 perform 两次。无论哪种方式,您都不会检查可能失败的第一次调用的结果。

标签: c++ c json curl libcurl


【解决方案1】:

CURLOPT_WRITEFUNCTION callback 函数server_response_stream 的第一个参数ptr 指向接收到的数据。该数据不是以空值结尾的。

字符串 += operator 必须接收一个指向空终止字符串的指针。

调用lastResponse += (const char*)ptr; 导致未定义的行为。字节必须以不同的方式附加到字符串中。您可以逐个字符地附加字符串,使用参数sizenmemb 来确定缓冲区的大小。

【讨论】:

  • 为什么需要这个?\
  • @Zero 我不确定你的意思是什么。哪一部分不清楚?我在答案中解释了问题。
  • 我的意思是当我直接设置 lastResponse 时是什么导致了未定义的行为?
  • @Zero lastResponse += (const char*)ptr; 行导致未定义的行为,更具体地说是对重载运算符的底层调用。
猜你喜欢
  • 1970-01-01
  • 2016-12-28
  • 2012-04-29
  • 1970-01-01
  • 1970-01-01
  • 2017-12-08
  • 2013-02-26
  • 1970-01-01
  • 2016-04-14
相关资源
最近更新 更多