使用libcurl在PUT请求中发送字符串

时间:2011-09-27 13:20:37

标签: c curl

我的代码如下所示:

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

但是正文是空的,意味着没有与请求一起发送json数据。

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

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

3 个答案:

答案 0 :(得分:40)

知道了:)

不要使用

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

答案 1 :(得分:1)

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

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

  

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

答案 2 :(得分:0)

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

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

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

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

背景故事:  我期待一个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_UPLOAD和CURLOPT_PUT或CUSTOM选项,都需要设置内容长度。

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

管理员注意:

请记住,代表50需要发表评论,所以我没有选择,只能分别发帖以便沟通。因此,当您考虑删除这些帖子时,请考虑这一点。