2011-09-27 38 views
13

Mi código es el siguiente:Enviar secuencia en la solicitud PUT con 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); 
} 

Qué no funciona, el programa simplemente se cuelga siempre.

En prueba.php estos son los encabezados de la solicitud me sale:

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

Pero el cuerpo está vacío, significa, no hay datos JSON se envía con la solicitud.

Lo que yo quiero hacer con libcurl es en realidad otra cosa entonces estos script de línea de comandos:

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

Respuesta

30

GOT IT :)

no uso

curl_easy_setopt(curl, CURLOPT_PUT, 1L); 

hacer una solicitud de medida y envíe los datos como 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

¡Perfecto! Y si desea evitar/suprimir la respuesta del servidor, debe configurar 'CURLOPT_WRITEFUNCTION' para recibir los datos o establecer' CURLOPT_WRITEDATA' en un manejador diferente 'FILE *'. – karlphillip

+1

¿Por qué no utilizar 'CURLOPT_UPLOAD' en lugar de' CURLOPT_CUSTOMREQUEST', como dice [la documentación] (http://curl.haxx.se/libcurl/c/CURLOPT_PUT.html)? –

+0

Tenía que hacer 'curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, NULL);' después de 'curl_easy_perform (curl);' para evitar que las próximas solicitudes también sean solicitudes PUT. –

0

Éste no funcionó para mí. TENÍA que usar UPLOAD y PUT para realizar esto correctamente. La respuesta que trabajó para mí está aquí:

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

precisa la función de devolución de llamada para READFILE y luego utilizar eso para copiar los datos en el rizo puntero ofrece en esa devolución de llamada.

Lo que en última instancia funcionó para mí fue asegurarme de configurar el tamaño del ARCHIVO usando CURLOPT_INFILESIZE o CURLOPT_INFILESIZE_LARGE según su carga útil. De lo contrario, se publica el problema en la historia de fondo.

Historia: que estaba esperando una solicitud JSON, pero utilizando la opción de venta CURL o este enfoque petición de encargo me sale el mismo resultado que haciendo esto a través de la consola

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 

Por otro lado haciendo la misma petición en la consola y la adición de un campo de datos (PUT -d "" URL) que me molesta lo que quiero:

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

en resumen, parece que necesito para averiguar las opciones CURL que va a hacer el equivalente del PUT -d "". También puede ver la diferencia entre ambas respuestas, en un caso el retorno es HTML y la conexión se cierra. En el otro caso, el contenido es JSON y la conexión se mantiene activa.

Basado en lo que he encontrado en caso de error 411:

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

El problema es que la longitud del contenido debe ser establecido independientemente de si utiliza CURLOPT_UPLOAD con CURLOPT_PUT o la opción Personalizar.

Por lo tanto, si tiene un flujo de datos lo tiene parece que TIENE que usar las opciones READDATA y READFUNCTION para determinar la longitud de sus datos.

Nota a admin:

Tenga en cuenta rep 50 es necesario para añadir comentarios así que no tienen más remedio que hacer puestos separados con el fin de comunicarse. Así que considere esto cuando esté pensando en eliminar estas publicaciones como se hizo en el pasado.

1

CURLOPT_PUT está en desuso, y ha sido por un tiempo. Debe usar CURLOPT_UPLOAD.

Para cantidades desconocidas de datos con HTTP, debe utilizar la codificación de transferencia fragmentada. Los documentos dicen CURLOPT_UPLOAD:

Si utiliza PUT a un servidor HTTP 1.1, puede cargar los datos sin conocer el tamaño antes de iniciar la transferencia si se utiliza codificación fragmentada. Habilite esto agregando un encabezado como "Transferir-Codificación: fragmentado" con CURLOPT_HTTPHEADER. Con HTTP 1.0 o sin transferencia fragmentada, debe especificar el tamaño.

Cuestiones relacionadas