使用libcurl在PUT请求中发送字符串
我的代码如下所示:
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
得到它了 :)
不要用
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_PUT
已被弃用,并且已经有一段时间了。 你应该使用CURLOPT_UPLOAD
。
对于使用HTTP的未知数据量,您应该使用分块传输编码。 CURLOPT_UPLOAD
文档说:
如果您将PUT用于HTTP 1.1服务器,则在开始传输之前,如果使用分块编码,则可以在不知道大小的情况下上载数据。 您可以通过使用CURLOPT_HTTPHEADER添加类似“Transfer-Encoding:chunked”的标头来启用此function。 对于HTTP 1.0或没有分块传输,您必须指定大小。
这个对我不起作用。 我必须使用UPLOAD和PUT才能正确执行此操作。 对我有用的答案是:
如何在不使用文件指针的情况下在libcurl中发送长PUT数据?
您需要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 < 411 Length Required 411 Length Required
nginx/1.1.19 * 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并且连接已关闭。 在另一种情况下,Content是JSON并且连接保持活动状态。
根据我在错误411上找到的内容:
http://www.checkupdown.com/status/E411.html
问题是无论是否使用CURLOPT_UPLOAD和CURLOPT_PUT或CUSTOM选项,都需要设置内容长度。
因此,如果您拥有数据流,那么您似乎必须使用READDATA和READFUNCTION选项来确定数据的长度。
管理员注意:
请记住,代表50需要发表评论,所以我没有选择,但要发布单独的post才能进行交流。 因此,当您考虑删除过去已完成的这些post时,请考虑这一点。