Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restful URLs with data in query string or request body?

What's the rule of thumb for passing data in a REST URL in the query string vs. the body of a request?

Ie: You're creating a service to add hockey players. You could go with:

PUT /players 
{ "name": Gretzky }

or

PUT /players?name=Gretzky

If you're passing a lot of data, you would need to go with option #1 as there is a limit on the URL length. But other than this, why not just use the query string to pass data?


Update: Removed comment that you could test option #2 in a browser. Realized (duh) that you can only do GET-s in your browser.

like image 882
Marcus Leon Avatar asked Oct 24 '09 22:10

Marcus Leon


People also ask

What is the difference between query parameter and body that you pass in API request?

Usually the content body is used for the data that is to be uploaded/downloaded to/from the server and the query parameters are used to specify the exact data requested.

Can we pass URL parameters in POST request?

If you know the URL parameters for your form post when the HTML page is sent to the client, you can tack those URL parameters on to the form's action attribute, otherwise JavaScript can set the URL parameters when the form is submitted.

How do I use a query parameter in REST API?

A REST API can have parameters in at least two ways: As part of the URL-path (i.e. /api/resource/parametervalue ) As a query argument (i.e. /api/resource? parameter=value )


3 Answers

Based on HTTP's definition of PUT, your first request is overwriting the list of players with a new list that contains just one player name. It is not adding to the list of players.

The second option does not really make much sense to me. Doing PUT without a body is not really consistent with the meaning of PUT.

Considering that one of the standard definitions of POST is to append to an existing resource, I'm not sure why you wouldn't do

POST /players 
{ "name": Gretzky }

If you are sure that all you player names are going to be unique then you could use PUT like this:

PUT /player/Gretzky
{ "name": Gretzky }

When you decide to do REST on HTTP you are agreeing to use HTTP in the way that is defined in RFC2616. That's what the uniform interface constraint means. And just to be pedantic, there is no such thing as a REST URL and you can't test either option in a browser because without javascript, you can't do a PUT in a browser.

like image 144
Darrel Miller Avatar answered Oct 19 '22 02:10

Darrel Miller


Option #1 is fine, though probably overkill. Option #1 is not fine because it's not idempotent.

Option #2 is a BAD idea. That would be misusing PUT. PUT should be used primarily when your request data payload is an opaque block of data, usually either large or hierarchical. Smaller, non-hierarchical payloads make more sense as POST.

Also, try to avoid changing state via query parameters. There's nothing technically dangerous about that if it's not a GET request, but it's not really RESTful.

In this case, what you should be doing is:

POST /players HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 12

name=Gretsky

This should return a 201 Created response. (There is an exception to this: If you don't create the resource immediately, and it might be rejected at a later time, use 202 Accepted instead.)

Writing a REST web service that uses more of HTTP than POST and GET should only be done after having read the HTTP specification. (It's a very useful read.) That rule is a bit looser if you're using a framework that makes all the decisions for you.

like image 39
Bob Aman Avatar answered Oct 19 '22 02:10

Bob Aman


My understanding of REST operations is that the URL uniquely identifies the resource, while the body of the request contains the representation of the resource. Given that, it's questionable whether either of your options are truly RESTful.

The first would be, assuming that the resource is named "Players" and a GET on that resource returns a list of players (I won't get into the question of whether that GET returns other resource URLs or not ... Fielding would say that it should, with individual requests to get the resource data).

The second would be, assuming that the request body contained information keyed by name "Gretsky". However, that requires you to generate the keys externally.

like image 2
kdgregory Avatar answered Oct 19 '22 01:10

kdgregory