Отправить строку в запросе 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, на самом деле не является чем-то иным, чем эта команда script:
curl -X PUT -H "Content-Type: application/json" -d '... some json ...' 127.0.0.1/test.php
Ответы
Ответ 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);
}
Ответ 2
CURLOPT_PUT
устарел, и он был на некоторое время. Вы должны использовать CURLOPT_UPLOAD
.
Для неизвестных объемов данных с помощью HTTP вы должны использовать кодировку с коротким передачей. CURLOPT_UPLOAD
docs говорят:
Если вы используете PUT на сервере HTTP 1.1, вы можете загружать данные, не зная размера, прежде чем начать передачу, если используете кодировку с чередованием. Вы включаете это, добавляя заголовок, например "Transfer-Encoding: chunked" с CURLOPT_HTTPHEADER. С помощью HTTP 1.0 или без перекоса, вы должны указать размер.
Ответ 3
Этот не работал у меня.
Я должен был использовать UPLOAD и PUT, чтобы выполнить это правильно.
Ответ, который работал у меня, был здесь:
Как отправить длинные PUT-данные в libcurl без использования указателей файлов?
Вам нужна функция обратного вызова для READFILE, а затем используйте ее для копирования ваших данных в предложения curl curler в этом обратном вызове.
В конечном итоге я работал над тем, чтобы установить размер FILE с помощью 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"}
В целом, похоже, мне нужно выяснить опции CURL, которые будут делать эквивалент PUT -d "". Также вы можете увидеть разницу между обоими ответами, в одном случае возврат HTML и соединение закрыто. В другом случае Content является JSON, и соединение поддерживается в режиме реального времени.
Основываясь на том, что я нашел при ошибке 411:
http://www.checkupdown.com/status/E411.html
Проблема в том, что длина содержимого должна быть установлена независимо от того, используете ли вы CURLOPT_UPLOAD с CURLOPT_PUT или опцией CUSTOM.
Итак, если у вас есть поток данных, у вас есть, то вам нужно использовать опции READDATA и READFUNCTION для определения длины ваших данных.
Примечание для администратора:
Имейте в виду, что rep 50 НЕОБХОДИМО оставлять комментарии, поэтому я НЕ ВЫБИРАЮ, но должен делать отдельные сообщения для общения. Поэтому рассмотрите это, когда вы думаете об удалении этих сообщений, как это было сделано в прошлом.