2011-09-27 58 views
13

我的代碼如下所示:發送字符串PUT請求與libcurl的

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 

回答

30

明白了:)

不使用

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

完美!如果你想防止/抑制來自服務器的回覆,你需要設置'CURLOPT_WRITEFUNCTION'來接收數據或者將'CURLOPT_WRITEDATA'設置爲不同的'FILE *'句柄。 – karlphillip

+1

爲什麼不使用'CURLOPT_UPLOAD'而不是'CURLOPT_CUSTOMREQUEST',就像[documentation](http://curl.haxx.se/libcurl/c/CURLOPT_PUT.html)所說的那樣? –

+0

我必須做'curl_easy_setopt(curl,CURLOPT_CUSTOMREQUEST,NULL);' 'curl_easy_perform(curl)'之後''以防止下一個請求成爲PUT請求。 –

0

這一個沒有爲我工作。 我必須使用UPLOAD和PUT才能正確執行此操作。 爲我工作的答案就在這裏:

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

您需要READFILE回調函數,然後用它來將數據複製到指針捲曲提供了該回調。

最終爲我工作的是確保使用CURLOPT_INFILESIZE或CURLOPT_INFILESIZE_LARGE設置FILE大小,具體取決於您的有效負載。否則,你會在背景故事中發佈問題。

背景故事: 我期待一個JSON請求,但無論使用的PUT捲曲選項或該自定義請求的方法,我得到了相同的結果通過控制檯

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「」網址)上得到我什麼,我想:

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「」。你也可以看到兩個響應之間的區別,在一種情況下,返回值是HTML並且連接已關閉。在另一種情況下,內容是JSON並且連接保持活動狀態。

基於我所上的錯誤411發現:

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

的問題是,內容長度需要不管你是否使用CURLOPT_UPLOAD與CURLOPT_PUT或自定義選項進行設置。

所以,如果你有一個數據流,你似乎必須使用READDATA和READFUNCTION選項來確定數據的長度。

注意管理員:

記住代表50要求發表評論,所以我別無選擇,只能作出獨立的職位,以溝通。因此,當您考慮刪除這些帖子時,請考慮這一點,因爲它過去已經完成。

1

CURLOPT_PUT已棄用,並已有一段時間。您應該使用CURLOPT_UPLOAD

對於未知數據量的HTTP,您應該使用分塊傳輸編碼。該CURLOPT_UPLOAD文檔說:

如果使用PUT到HTTP 1.1服務器,你可以上傳數據,而如果使用分塊編碼開始轉移之前知道大小。通過使用CURLOPT_HTTPHEADER添加一個類似「Transfer-Encoding:chunked」的頭來啓用此功能。使用HTTP 1.0或無分塊傳輸時,您必須指定大小。