【问题标题】:Send string in PUT request with libcurl使用 libcurl 在 PUT 请求中发送字符串
【发布时间】:2011-09-27 13:20:36
【问题描述】:

我的代码如下所示:

curl = curl_easy_init();

if (curl) {
    headers = curl_slist_append(headers, client_id_header);
    headers = curl_slist_append(headers, "Content-Type: application/json");

    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 
    curl_easy_setopt(curl, CURLOPT_URL, "127.0.0.1/test.php");  
    curl_easy_setopt(curl, CURLOPT_PUT, 1L);

    res = curl_easy_perform(curl);
    res = curl_easy_send(curl, json_struct, strlen(json_struct), &io_len);

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
}

这不起作用,程序永远挂起。

在 test.php 中,这些是我得到的请求标头:

array(6) {
  ["Host"]=>
  string(9) "127.0.0.1"
  ["Accept"]=>
  string(3) "*/*"
  ["Transfer-Encoding"]=>
  string(7) "chunked"
  ["X-ClientId"]=>
  string(36) "php_..."
  ["Content-Type"]=>
  string(16) "application/json"
  ["Expect"]=>
  string(12) "100-continue"
}

但是body是空的,意味着请求没有发送json数据。

我想用 libcurl 做的实际上就是这些命令行脚本:

curl -X PUT -H "Content-Type: application/json" -d '... some json ...' 127.0.0.1/test.php

【问题讨论】:

    标签: c curl


    【解决方案1】:

    知道了:)

    不要使用

    curl_easy_setopt(curl, CURLOPT_PUT, 1L);
    

    发出自定义请求并将数据作为 POSTFIELDS 发送:

    curl = curl_easy_init();
    
    if (curl) {
        headers = curl_slist_append(headers, client_id_header);
        headers = curl_slist_append(headers, "Content-Type: application/json");
    
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 
        curl_easy_setopt(curl, CURLOPT_URL, request_url);  
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); /* !!! */
    
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_struct); /* data goes here */
    
        res = curl_easy_perform(curl);
    
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    

    【讨论】:

    • 完美!如果您想阻止/抑制来自服务器的回复,您需要设置CURLOPT_WRITEFUNCTION 以接收数据或将CURLOPT_WRITEDATA 设置为不同的FILE* 句柄。
    • 为什么不使用CURLOPT_UPLOAD 而不是CURLOPT_CUSTOMREQUEST,就像documentation 所说的那样?
    • 我必须做 'curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);'在'curl_easy_perform(curl);'之后以防止下一个请求也成为 PUT 请求。
    • CURLOPT_UPLOAD 对我不起作用,即使我认为这是正确的方法。所以我尝试了CURLOPT_CUSTOMREQUEST 选项。它运作良好。我不知道CURLOPT_UPLOADCURLOPT_CUSTOMREQUEST 有什么不同。我想他们会以正确的方式工作。
    【解决方案2】:

    CURLOPT_PUT 已被弃用,并且已经有一段时间了。你应该使用CURLOPT_UPLOAD

    对于未知数量的 HTTP 数据,您应该使用分块传输编码。 CURLOPT_UPLOAD 文档说:

    如果您使用 PUT 到 HTTP 1.1 服务器,如果您使用分块编码,则可以在开始传输之前不知道大小的情况下上传数据。您可以通过使用 CURLOPT_HTTPHEADER 添加诸如“Transfer-Encoding: chunked”之类的标头来启用此功能。使用 HTTP 1.0 或没有分块传输,您必须指定大小。

    【讨论】:

      【解决方案3】:

      这个对我不起作用。 我必须使用 UPLOAD 和 PUT 才能正确执行此操作。 对我有用的答案在这里:

      How do I send long PUT data in libcurl without using file pointers?

      您需要 READFILE 的回调函数,然后使用它将数据复制到该回调中 curl 提供的指针。

      最终对我有用的是确保我使用 CURLOPT_INFILESIZE 或 CURLOPT_INFILESIZE_LARGE 设置文件大小,具体取决于您的有效负载。否则,您会在背景故事中发布问题。

      背景故事: 我期待一个 JSON 请求,但使用 PUT CURL 选项或这种自定义请求方法我得到与通过控制台执行此操作相同的结果

       curl -H "Accept:application/json" -H "Authorization:authxxxx" -v -X PUT "http://server.xxxdomain.com/path0/path1/path2/state?data1=1&data2=1421468910543&data3=-3"
      
      
      * Adding handle: conn: 0x7fd752003a00
      * Adding handle: send: 0
      * Adding handle: recv: 0
      * Curl_addHandleToPipeline: length: 1
      * - Conn 0 (0x7fd752003a00) send_pipe: 1, recv_pipe: 0
      * About to connect() to server.xxxdomain.com port 80 (#0)
      *   Trying ipaddress...
      * Connected to api-qos.boingodev.com (ipaddress) port 80 (#0)
      > PUT /path0/path1/path2/done?data1=1&data2=1421468910543&data3=-3 HTTP/1.1
      > User-Agent: curl/7.30.0
      > Host: server.xxxdomain.com
      > Accept:application/json
      > Authorization:authxxxx
      > 
      < HTTP/1.1 411 Length Required
      * Server nginx/1.1.19 is not blacklisted
      < Server: nginx/1.1.19
      < Date: Sat, 17 Jan 2015 04:32:18 GMT
      < Content-Type: text/html
      < Content-Length: 181
      < Connection: close
      < 
      <html>
      <head><title>411 Length Required</title></head>
      <body bgcolor="white">
      <center><h1>411 Length Required</h1></center>
      <hr><center>nginx/1.1.19</center>
      </body>
      </html>
      * Closing connection 0
      

      另一方面,在控制台上发出相同的请求并添加数据字段(PUT -d "" URL)得到我想要的:

      curl -H "Accept:application/json" -H "authxxxx" -v -X PUT -d "" "http://server.xxxdomain.com/path0/path1/path2/state?data1=1&data2=1421468910543&data3=-3"
      * Adding handle: conn: 0x7fe8aa803a00
      * Adding handle: send: 0
      * Adding handle: recv: 0
      * Curl_addHandleToPipeline: length: 1
      * - Conn 0 (0x7fe8aa803a00) send_pipe: 1, recv_pipe: 0
      * About to connect() to server.xxxdomain.com port 80 (#0)
      *   Trying ipaddress...
      * Connected to server.xxxdomain.com (ipaddress) port 80 (#0)
      > PUT /path0/path1/path2/state?data1=1&data2=1421468910543&data3=-3" HTTP/1.1
      > User-Agent: curl/7.30.0
      > Host: server.xxxdomain.com
      > Accept:application/json
      > Authorization:authxxxx
      > Content-Length: 0
      > Content-Type: application/x-www-form-urlencoded
      > 
      < HTTP/1.1 200 OK
      * Server nginx/1.1.19 is not blacklisted
      < Server: nginx/1.1.19
      < Date: Sat, 17 Jan 2015 17:16:59 GMT
      < Content-Type: application/json
      < Content-Length: 32
      < Connection: keep-alive
      < 
      * Connection #0 to host server.xxxdomain.com left intact
      {"code":"0","message":"Success"}
      

      总而言之,我似乎需要找出与 PUT -d "" 等效的 CURL 选项。您还可以看到两种响应之间的区别,在一种情况下,返回是 HTML 并且连接已关闭。在另一种情况下,内容是 JSON,并且连接保持活动状态。

      根据我发现的错误 411:

      http://www.checkupdown.com/status/E411.html

      问题在于,无论您是使用带有 CURLOPT_PUT 的 CURLOPT_UPLOAD 还是 CUSTOM 选项,都需要设置内容长度。

      因此,如果您有一个数据流,您似乎必须使用 READDATA 和 READFUNCTION 选项来确定数据的长度。

      管理员注意:

      请记住,发布 cmets 需要代表 50,所以我别无选择,只能发布单独的帖子以进行交流。因此,当您考虑像过去那样删除这些帖子时,请考虑这一点。

      【讨论】:

        猜你喜欢
        • 2015-02-28
        • 2014-01-15
        • 1970-01-01
        • 2011-05-13
        • 1970-01-01
        • 2022-12-25
        • 2020-12-02
        • 1970-01-01
        • 2014-06-05
        相关资源
        最近更新 更多