C语言 使用 libcurl 在 PUT 请求中发送字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7569826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Send string in PUT request with libcurl
提问by Max
My code looks like this:
我的代码如下所示:
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);
}
Which doesnt work, the program just hangs forever.
哪个不起作用,程序只是永远挂起。
In test.php these are the request headers I get:
在 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"
}
But the body is empty, means, no json data is sent with the request.
但是正文是空的,这意味着没有随请求发送 json 数据。
What I want to do with libcurl is actually nothing else then these command line script:
我想用 libcurl 做的实际上就是这些命令行脚本:
curl -X PUT -H "Content-Type: application/json" -d '... some json ...' 127.0.0.1/test.php
回答by Max
Got it :)
知道了 :)
Dont use
不要使用
curl_easy_setopt(curl, CURLOPT_PUT, 1L);
Make a custom request and send the data as POSTFIELDS:
发出自定义请求并将数据作为 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);
}
回答by Nathan Ward
CURLOPT_PUTis deprecated, and has been for a while. You should use CURLOPT_UPLOAD.
CURLOPT_PUT已弃用,并且已经有一段时间了。你应该使用CURLOPT_UPLOAD.
For unknown amounts of data with HTTP, you should be using chunked transfer encoding. The CURLOPT_UPLOADdocs say:
对于未知数量的 HTTP 数据,您应该使用分块传输编码。该CURLOPT_UPLOAD文件说:
If you use PUT to a HTTP 1.1 server, you can upload data without knowing the size before starting the transfer if you use chunked encoding. You enable this by adding a header like "Transfer-Encoding: chunked" with CURLOPT_HTTPHEADER. With HTTP 1.0 or without chunked transfer, you must specify the size.
如果您使用 PUT 到 HTTP 1.1 服务器,如果您使用分块编码,则可以在开始传输之前不知道大小的情况下上传数据。您可以通过使用 CURLOPT_HTTPHEADER 添加诸如“Transfer-Encoding: chunked”之类的标头来启用此功能。使用 HTTP 1.0 或不使用分块传输,您必须指定大小。
回答by einarc
This one did not work for me. I HAD to use UPLOAD and PUT to perform this correctly. The answer that worked for me is here:
这个对我不起作用。我必须使用 UPLOAD 和 PUT 才能正确执行此操作。对我有用的答案在这里:
How do I send long PUT data in libcurl without using file pointers?
如何在不使用文件指针的情况下在 libcurl 中发送长 PUT 数据?
You need the callback function for READFILE and then use that to copy your data to the pointer curl offers in that callback.
您需要 READFILE 的回调函数,然后使用它来将数据复制到该回调中 curl 提供的指针。
What ultimately worked for me was to make sure I set the FILE size using either CURLOPT_INFILESIZE or CURLOPT_INFILESIZE_LARGE depending on your payload. Otherwise you get the problem posted in the backstory.
最终对我有用的是确保我根据您的有效负载使用 CURLOPT_INFILESIZE 或 CURLOPT_INFILESIZE_LARGE 设置文件大小。否则,您会在背景故事中发布问题。
Backstory: I was expecting a JSON request but using either the PUT CURL option or this custom request approach I get the same result as doing this via console
背景故事:我期待 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
On the other hand making the same request on the console and adding a data field (PUT -d "" URL)gets me what I want:
另一方面,在控制台上发出相同的请求并添加一个数据字段(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"}
In summary it looks like I need to figure out the CURL options that'll do the equivalent of PUT -d "". Also you can see the difference between both response, in one case the return is HTML and the connection is closed. In the other case the Content is JSON and the connection is kept alive.
总而言之,看起来我需要弄清楚 CURL 选项,这些选项将与 PUT -d "" 等效。您还可以看到两种响应之间的区别,在一种情况下,返回的是 HTML 并且连接已关闭。在另一种情况下,内容是 JSON 并且连接保持活动状态。
Based on what I've found on error 411:
根据我在错误 411 中发现的内容:
http://www.checkupdown.com/status/E411.html
http://www.checkupdown.com/status/E411.html
The problem is that the content length needs to be set regardless of whether you use CURLOPT_UPLOAD with CURLOPT_PUT or the CUSTOM option.
问题是,无论您使用 CURLOPT_UPLOAD 和 CURLOPT_PUT 还是 CUSTOM 选项,都需要设置内容长度。
So, if you have a stream of data you have it seems you HAVE to use the READDATA and READFUNCTION options to determine the length of your data.
所以,如果你有一个数据流,你似乎必须使用 READDATA 和 READFUNCTION 选项来确定数据的长度。
Note to admin:
管理员注意事项:
Keep in mind rep 50 is REQUIRED to post comments so I HAVE NO CHOICE but to make separate posts in order to communicate. So consider this when you are thinking about deleting these posts as it has been done in the past.
请记住,代表 50 需要发表评论,所以我别无选择,只能单独发帖进行交流。因此,当您考虑像过去那样删除这些帖子时,请考虑这一点。

