This one did not work for me.
I HAD to use UPLOAD and PUT to perform this correctly.
The answer that worked for me is here:
How do I send long PUT data in libcurl without using file pointers?
You need the callback function for READFILE and then use that to copy your data to the pointer curl offers in that callback.
What ultimately worked for me was to make sure I set the FILE size using either CURLOPT_INFILESIZE or CURLOPT_INFILESIZE_LARGE depending on your payload. Otherwise you get the problem posted in the backstory.
Backstory:
I was expecting a JSON request but using either the PUT CURL option or this custom request approach I get the same result as doing this via console
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
On the other hand making the same request on the console and adding a data field (PUT -d "" URL)gets me what I want:
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"}
In summary it looks like I need to figure out the CURL options that'll do the equivalent of PUT -d "". Also you can see the difference between both response, in one case the return is HTML and the connection is closed. In the other case the Content is JSON and the connection is kept alive.
Based on what I've found on error 411:
http://www.checkupdown.com/status/E411.html
The problem is that the content length needs to be set regardless of whether you use CURLOPT_UPLOAD with CURLOPT_PUT or the CUSTOM option.
So, if you have a stream of data you have it seems you HAVE to use the READDATA and READFUNCTION options to determine the length of your data.
Note to admin:
Keep in mind rep 50 is REQUIRED to post comments so I HAVE NO CHOICE but to make separate posts in order to communicate. So consider this when you are thinking about deleting these posts as it has been done in the past.