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.
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With