Senden Sie eine Zeichenfolge in einer PUT-Anfrage mit libcurl

Lesezeit: 6 Minuten

Benutzeravatar von Max
max

Mein Code sieht so aus:

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

Was nicht funktioniert, das Programm hängt sich einfach für immer auf.

In test.php sind dies die Anforderungsheader, die ich bekomme:

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

Aber der Body ist leer, d.h. es werden keine JSON-Daten mit der Anfrage gesendet.

Was ich mit libcurl machen möchte, ist eigentlich nichts anderes als dieses Kommandozeilenskript:

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

Habe es 🙂

Nicht verwenden

curl_easy_setopt(curl, CURLOPT_PUT, 1L);

Stellen Sie eine benutzerdefinierte Anfrage und senden Sie die Daten als 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);
}

  • Perfekt! Und wenn Sie die Antwort des Servers verhindern/unterdrücken möchten, müssen Sie das einstellen CURLOPT_WRITEFUNCTION um die Daten zu empfangen oder einzustellen CURLOPT_WRITEDATA zu einem anderen FILE* handhaben.

    – Karl Philipp

    23. Februar 2012 um 12:59 Uhr


  • Warum nicht verwenden CURLOPT_UPLOAD anstatt CURLOPT_CUSTOMREQUESTwie Dokumentation sagt?

    – Rémy Lebeau

    14. Oktober 2014 um 2:27 Uhr

  • Ich musste ‘curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);’ nach ‘curl_easy_perform(curl);’ um zu verhindern, dass die nächsten Anfragen ebenfalls PUT-Anfragen sind.

    – Pieter Günst

    30. März 2015 um 14:39 Uhr


  • CURLOPT_UPLOAD funktioniert bei mir nicht, auch wenn ich denke, dass das der richtige Weg ist. Also versuchte ich es CURLOPT_CUSTOMREQUEST Möglichkeit. Es funktioniert gut. Ich weiß nicht, was zwischen unterschiedlich ist CURLOPT_UPLOAD Und CURLOPT_CUSTOMREQUEST. Ich denke, sie würden richtig funktionieren.

    – DDukDDak99

    28. Oktober 2020 um 6:44 Uhr

Benutzeravatar von Nathan Ward
Nathan Ward

CURLOPT_PUT ist veraltet, und das schon seit einiger Zeit. Du solltest benutzen CURLOPT_UPLOAD.

Bei unbekannten Datenmengen mit HTTP sollten Sie Chunked Transfer Encoding verwenden. Der CURLOPT_UPLOAD docs sagen:

Wenn Sie PUT auf einen HTTP 1.1-Server verwenden, können Sie Daten hochladen, ohne die Größe zu kennen, bevor Sie mit der Übertragung beginnen, wenn Sie Chunked Encoding verwenden. Sie aktivieren dies, indem Sie einen Header wie „Transfer-Encoding: chunked“ mit CURLOPT_HTTPHEADER hinzufügen. Bei HTTP 1.0 oder ohne Chunked Transfer müssen Sie die Größe angeben.

Benutzeravatar von eco
Öko

Dieser hat bei mir nicht funktioniert. Ich musste UPLOAD und PUT verwenden, um dies korrekt durchzuführen. Die Antwort, die für mich funktioniert hat, ist hier:

Wie sende ich lange PUT-Daten in libcurl, ohne Dateizeiger zu verwenden?

Sie benötigen die Callback-Funktion für READFILE und verwenden diese dann, um Ihre Daten in die Zeiger-Curl-Angebote in diesem Callback zu kopieren.

Was letztendlich für mich funktionierte, war sicherzustellen, dass ich die Dateigröße je nach Nutzlast entweder mit CURLOPT_INFILESIZE oder CURLOPT_INFILESIZE_LARGE festlegte. Andernfalls wird das Problem in der Hintergrundgeschichte gepostet.

Hintergrundgeschichte: Ich habe eine JSON-Anfrage erwartet, aber mit der PUT CURL-Option oder diesem benutzerdefinierten Anfrageansatz erhalte ich das gleiche Ergebnis wie über die Konsole

 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

Auf der anderen Seite bekomme ich, wenn ich dieselbe Anfrage auf der Konsole mache und ein Datenfeld hinzufüge (PUT -d “” URL), was ich will:

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

Zusammenfassend sieht es so aus, als müsste ich die CURL-Optionen herausfinden, die das Äquivalent von PUT -d “” ausführen. Sie können auch den Unterschied zwischen beiden Antworten sehen, in einem Fall ist die Rückgabe HTML und die Verbindung wird geschlossen. Im anderen Fall ist der Inhalt JSON und die Verbindung wird aufrechterhalten.

Basierend auf dem, was ich zu Fehler 411 gefunden habe:

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

Das Problem besteht darin, dass die Inhaltslänge festgelegt werden muss, unabhängig davon, ob Sie CURLOPT_UPLOAD mit CURLOPT_PUT oder der CUSTOM-Option verwenden.

Wenn Sie also einen Datenstrom haben, müssen Sie anscheinend die Optionen READDATA und READFUNCTION verwenden, um die Länge Ihrer Daten zu bestimmen.

Hinweis an den Administrator:

Denken Sie daran, dass rep 50 ERFORDERLICH ist, um Kommentare zu posten, also habe ich keine andere Wahl, als separate Posts zu erstellen, um zu kommunizieren. Berücksichtigen Sie dies also, wenn Sie daran denken, diese Beiträge zu löschen, wie es in der Vergangenheit geschehen ist.

1444120cookie-checkSenden Sie eine Zeichenfolge in einer PUT-Anfrage mit libcurl

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy