Reading PUT data from piped cURL in Sinatra
curl, pipe, put, request, sinatra
Solution
I think the curl command from the client is misusing the `-T` flag. `-T` is for uploading a file, not sending data. Normally, when you don't provide a destination file name, `-T` will use the local file name for the upload. For example, `curl -X PUT -T "bar.txt" http://localhost:8090/` will upload the local file `bar.txt` to the remote location `http://localhost:8090/bar.txt`. Since your client code pipes stdin instead of specifying a file, no local file name exists. And since your client code does not specify any destination file name, it will produce undefined results. I would consider it non-standard behavior for node.js to accept the contents of a file upload as data in the request body.
Your second example using the `-d` flag is the proper way to send data. I really think the best solution would be to change the client code, but you can still pipe stdin if you want to. Just use `-d` instead of `-T`, like so:
echo "foo" | curl -X PUT -d @- http://localhost:8090/
Problem
I'm rewriting a small server backend in Sinatra, and currently the client talks to it via cURL calls such as `echo "foo" | curl -X PUT -T - http://localhost:8090/`. The problem is, in my `put` method in Sinatra, the `request.body.read` is always empty, even after I call `rewind` on it. Furthermore, the `params` hash is completely empty. What's weird is that if I do `curl -X PUT -d 'foo' http://localhost:8090/` instead it works. Also, in node.js I can read it fine using the `request.on('data')` and `request.on('end')` functions. Is there any way to read the `PUT` body in Sinatra? I would like to avoid changing the client code if at all possible.