micha / resty

Little command line REST client that you can use in pipelines (bash or zsh).
MIT License
2.65k stars 143 forks source link

Query Parameters for PUT and DELETE #20

Closed BigBlueHat closed 13 years ago

BigBlueHat commented 13 years ago

First, Resty is fabulous! :) Thanks for building it.

Second, it'd be great if it were possible to pass query parameters to PUT and DELETE methods. I'd really love to be able to put them inline with the URL (ex: /url?param=value&other=value), but being able to use -d or similar would be fine at this point. Perhaps an alternative scheme would be a -q switch that could take a string of query parameters: -q "param=value&other=value"

This feature would make working with CouchDB a good bit easier given it's need for "rev=1-...." whenever PUT-ing or DELETE-ing documents or attachments. I'm getting around it now using -H "If-Match: 1-..." (the Etag-based solution), but there are likely other API's that aren't that flexible.

Thanks for considering this idea, Benjamin

micha commented 13 years ago

Hi Benjamin,

Thanks, glad you find it useful! I think you can do what you want (sending query parameters with the request) by using the curl options -d foo=bar along with -G. The -d option causes curl to send the parameter foo with the value bar, but by default it sends it in the body of the request, as content-type application/x-www-form-urlencoded. Adding the -G option removes this behavior and causes curl to send the parameters in the uri query part.

Example:

$ resty localhost:9090
http://localhost:9090*
$ DELETE /posts/3 -d param1=value1 -d param2=value2 -G
{ "status": "OK" }
$ cat newpost.json | PUT /posts/3 -d foo=bar -G 
{ "status": "OK" }

The reason you need to use the -d option is because resty will urlencode the uri you specify on the command line.

The documentation is not clear and I have had a number of people ask me about this. Do you have any recommendations about how I could improve the docs?

Regards, Micha

micha commented 13 years ago

Ah. I see I spoke too soon. I will think about this and see if I can come up with a fix. The problem is with sending data in both the query string and the body in the same request.

micha commented 13 years ago

OK. So the only way I know to send a request with both a query string and data in the request body via curl is like this:

 echo '{"asdf":"foo"}' |curl --raw -T . -d foo=bar -G http://localhost:9090/asdf/

That uploads the data with content-encoding = chunked, though, and you can only send the upload stuff via stdin or a file. You can't just put it on the command line. Unfortunately, the way resty manipulates the data prior to applying the command line args to curl makes it so you can't use -T with resty at the moment. I can probably work it in, but the interface needs to be carefully considered I think, so as not to overly complicate things or introduce incompatibilities with curl's command line interface. What do you think?

Another possibility is to disable url encoding of the path, and then just type the path as /asdf?foo=bar&baz=baf.

The more I think about it, the more I like your -q option.

BigBlueHat commented 13 years ago

The first thing I tried was putting the query string directly with the URL, until I realized that URL's were automagically encoded. The auto-encoding is a nice feature, but I wonder if it could be narrowed a bit to avoid standard URL components (at least in their expected places. The -q option would be a fairly simple work around if strategic URL encoding is overkill or overly complex.

Off to play with Resty some more. :)

BigBlueHat commented 13 years ago

Oh, and forgot to mention (fwiw) this bit of curl from CouchDB: The Definitive Guide:

curl -vX PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af/artwork.jpg?rev=2-2739352689 --data-binary @artwork.jpg -H "Content-Type: image/jpg"
micha commented 13 years ago

The only problem with -q would be that it would shadow the curl option, but that option to curl does not expect an argument, and it must be the first one, so maybe it would work. So if you use -q "foo=bar&baz=baf" it would add the query string, but -q alone would be passed to curl...

The reason for the url encoding business was for working with Persevere, because you often need to put json queries in the url, and they often contain characters like question marks and ampersands etc.

micha commented 13 years ago

I added a -Q option which disables url encoding. Would that work for you? So you can do:

$ resty http://127.0.0.1:5984 
http://127.0.0.1:5984*
$ PUT '/albums/6e1295ed6c29495e54cc05947f18c8af/artwork.jpg?rev=2-2739352689' @image.jpg -Q -v -H 'Content-Type: image/jpg'
{"status" : "fine"}

If you wanted to always add the -Q option you could add it (or any other options you will want to use for all requests) to the resty command, and it will be added to all subsequent GET, PUT, etc requests until the next time you run resty.

micha commented 13 years ago

I also added your -q option:

$ cat myfile.json | PUT /the/path -q 'param=value&other=something'
{ "status": "ok" }
BigBlueHat commented 13 years ago

Micha, you rock! Just tested them both, and they work fabulously! The choice to add both options was a great idea.

Resty's not a core part of my toolkit, so I look forward to staying in touch.

Again, great (and speedy) work, Micha!

dikshaSahni commented 6 years ago

Is it possible to send Query params with PUT request in Java Rest API?

AdrieanKhisbe commented 6 years ago

@DevDik What Java rest api are you talking about, you're probably looking for https://github.com/beders/Resty :)