Should this be a POST or a PUT - rest

So I know that PUT is idempotent, whereas POST is not. Let's say I have an 'add to team' type method. If you're not already on the indicated team, you're added. If you are on the team already, then nothing happens.
I'm thinking that should therefore be a PUT, not a POST, because whether I call it once or a million times, the result on the server is the same. You're on the team.
Is this correct thinking, or am I still confused?

To create a team it is a POST on the teamS resource. Something like below
POST http://myservices.com/teams/
To create a team member it is a POST on the team resource. Something like below
POST http://myservices.com/teams/98098LKJLKLKJ/
or
POST http://myservices.com/teams/98098LKJLKLKJ/members (recommended)
To update a team information it should be something like
PUT http://myservices.com/teams/98098LKJLKLKJ/
To update a team member information it should be something like
PUT http://myservices.com/teams/98098LKJLKLKJ/members/90JN998J98J/ (recommended)
OR
PUT http://myservices.com/teams/98098LKJLKLKJ/90JN998J98J/

Related

What should be the Rest URL for the action "Move the competitor from team1 to to team2"

I am looking for a good URL, following REST principes, to "Move the competitor from team1 to to team2
My first guess is :
/teams/{oldTeamId}/{newTeamId}/competitors/{competitorId}/move
But it doesn't look much like REST.
Should I break it into 2 basics calls ?
Remove competitor from team1,
Add competitor to team2,
Should I remove some data from URL and pass it into the body ?
I don't really know what to do for this one.
Think about how you would implement this API as a web site.
You would probably have a link to a form -- it might be a form where the competitor, old team, and new team are all blank, or it might be a form where the competitor and old team are pre-populated. Your consumer updates the default information in the form as required, and submits it.
Notice the first point (raised by Roman Vottner as well) -- your consumer doesn't need to look at the URL at all. The client knows the HTML form processing rules, so it can create the correct HTTP request without knowing anything about the domain.
The second point is that, since the client is just submitting the form to wherever the HTML tells it to, you can make that anything you want.
One of the interesting properties of HTTP is cache invalidation. See RFC 7234, any non error response to an unsafe request will invalidate all cached representations of one resource.
So you can choose which resource gets invalidated by specifying its URI as the target of the form. In effect, it gives you a mechanism for ensuring that a consumer can read its own writes.
So some reasonable choices for the target might be
/teams/{oldTeamId}
if the team roster is the most important thing. Or
/competitors/{competitorId}
if the resource that describes the player is what is most important.
I don't really know what to do for this one.
Concentrate on make it easy to use. Your resource model is not your domain model is not your data model.
It will likely be useful to watch Jim Webber's talk REST: DDD In the Large to get clearer insights into what your "REST" API should really look like.
To answer your questions, I would not break it into two calls, I would however take some data from that (GET) url and put it in the body of your request. The request would probably be a POST or PUT (or maybe even patch), but definitely not a GET since something is actually changing.
As for a solution, how about a POST request to a /transfer. After all you are (could be) creating a new transfer which takes for example the player, their new team and maybe their old team.
I would use URL to identify the resource which in this case seems to be a competitor's team.
So would
Make the url as /competitors/{competitorId}/teams
Make the call PUT
Have a body with newTeamId and if required the oldTeamId.

REST API + hacks/REST + RPC hybrid. Do I get it right?

TL;DR How to mix REST requests with some non-REST requests in SPA(frontend/backend)? Or might be I just get REST wrong?
We are planning new API for SPA and mobiles(plus probably some 3rd parties). There will be some requests which, I suppose, can't be covered by REST.
I am speaking mostly about requests which would make backend do something, which would modify state of document or give some additional info, based on document, but request itself is rather simplistic.
Here is really easy example. I want to add a comment to blog post. For example I might do it like this:
Create comment. POST /comment
Create connection between author and comment. POST /comment_author or PUT /comment with author_id.
Create connection between comment and post. POST /comment_post or PUT /comment with post_id.
I also could do something like POST /comment with {author_id, post_id} which actually seems most logical here.
Everything did work, comment added to blogpost and associated with author.
Now customer wants to get statistics for his comment, like words stats and letters stats. As a part of request I pass comment_id. Backend might update comment with stats data, it might create separate entity and link it with comment or it might just send me those stats for this comment without saving.
So what would be the choices?
I can do something like:
GET/PUT /comment/:id/stats. For me it seems already hack, because as a result I don't want a document of type comment, but document of different type. As well as I don't send stats with request, I calculate them on backend so using PUT seems wrong.
POST/GET /comment_stats/:comment_id. Seems legit, but if I don't have a document/entity of type comment_stats, that would mean that I actually ask backend to create something, backend would reply me OK/Created, but actually I don't have this document somewhere saved.
So, while I understand REST != CRUD, I thought to use REST for simple CRUD and, for cases like that, to use RPC. So in RPC scenario I would just call POST comment.stats(comment_id)
My questions are what would be better choice in this situation, as well as are my thoughts about rest/rpc right?
I would go with GET /comment_stats/:comment_id for proper separation of concerns, so that report code doesn't clutter the comment resource.
It doesn't matter if you don't actually have a comment_stats document, or how the data is represented on your backend. The REST API is just an abstraction over your backend.
In general, for any non-CRUD action like this, it's better anyway to create a new resource and deal with it as if it was a "machine": you send some instructions to the machine (via a GET or POST call). The machine executes it and then returns the result. A simple example would be an endpoint to convert images: you create an /image_converter end point (the machine), you POST an image to it, it converts it, and sends back the image. /image_converter would have no associated entity/document in the database but for the end user it's still a resource with a logical behavior.

Restful API: Is it meaningful to send PUT without enclosed entity?

Consider the following scenario:
There are two existing entity: shopping card #1 and item #1. I want to add item #1 to shopping card #1. There are two possible ways to design a Restful api:
1:
Without body:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/1
Host: myshoppingsite.com
2: With body (having enclosed-entity):
PUT http://myshoppingsite.com/api/shoppingcards/1/items/
Host: myshoppingsite.com
{itemId: "1"}
Actually, I cannot decide which one is better and is more meaningful in terms of restfulness. Any idea?
(Note: I believe the http method should be PUT because of idempotency, but this is not my question here.)
PS: The problem I have with the first design is that there is no such enclosed entity in the request. Linguistically put is a transitive verb, so I expect somebody puts something somewhere. I think the same story somehow is in the HTTP world.
PUT is a HTTP verb that is supposed to create or replace the target URI, so this makes your first option immediately wrong. This request should replace all the items in your shopping cart:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/
Since you want to add something to your shopping cart, this is not an option. This leaves effectively two options. First: the common one:
POST http://myshoppingsite.com/api/shoppingcards/1/items/
POST can mean many things, but in the context of REST services it's often used to append something to a collection. However, you mention that you want idempotence. You have two options here, first you can still use POST and within the context of your API guarantee that the request will be idempotent. Using POST does not mean that it's per definition non-idempotent, it just means that the HTTP spec alone does not guarantee it. That does not prevent you from making the request idempotent.
The other option is indeed PUT:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/1
Your have a concern with that though, because in the context of your API you say that the request body would end up empty.
The reason for this is that you attach special to the last /1 in the url, and I think this what's wrong. If you want to follow REST best practices, then urls should not have any special meaning.
I think a saner way to do this, if you insist on using PUT is to get rid of the notion of "an id". That concept only exists in your database and should not make its way to the API.
Instead, I imagine that your service has a list of products such as this one:
http://myshoppingsite.com/products/1
To add a product to a shopping cart using PUT, this request might look something like this:
PUT http://myshoppingsite/api/shoppingcards/1/items/[completely-arbitrary-string-or-perhaps-a-uuid]
Content-Type: application/json
{
"product" : "http://myshoppingsite.com/products/1",
"quantity" : 5
}
Personally, I would just use POST though.
Q: there should be some information about the product you are addisng, no? Yes and that information is part of Uril. Why is it bad?
I'm not saying it's bad, I'm saying it's not RESTful. Pick up any book about REST and you will see this confirmed. This might also be a good place to start reading more about what REST is:
http://martinfowler.com/articles/richardsonMaturityModel.html
I would personally say that very little people build true RESTful services. This is why I also want to specifically point out that I don't want to say this is bad or good for your specific API, it's simply not RESTful.
What if I don't care about these principles and want to keep my special-meaning url scheme?
Well that's a fair point, but then we've gone beyond the original question here. If you want to design an API where the last bit of the url is actually the 'representation' of the item in your shopping cart, then yes I agree that having it also in the body is redundant.
In that situation I'd say, keep the request body empty. Just don't call it REST I guess.

REST API: Best way to do/undo an action on a resource

Note: I consider here that POST means "create" and PUT means "update", as GitHub does. This is not the place to argument in favor of POST or PUT.
I have a company resource and an assign action. I'm wondering how to translate this behavior in my REST API.
I thought about something like:
PUT /company/:id/assign
user_id: 5
What about if I want to unassign this user?
Should I use a boolean as a parameter?
Should I use an unassign action?
Should I use use another HTTP verb?
On the latest GitHub API I saw how to star a gist:
PUT /gists/:id/star
Why not, but how to unstar a gist:
DELETE /gists/:id/star
It seems pretty strange to me. You are updating an action on a resource and deleting it. Weird. I could understand whether POST instead of PUT.
POST /gists/:id/star and DELETE /gists/:id/star seems more logic to me. What do you think?
EDIT: I'm going to work with POST and DELETE. But as this is not possible to send data with the DELETE method, I have to pass the user_id in URL:
POST /company/:id/assign/:user_id
DELETE /company/:id/assign/:user_id
Using a boolean is not really clear. I could consider it as a non-obvious argument term. Consider that the most the API interpretation is obvious, the most your syntax is good.
Using the DELETE method is, finally, the best option you can choose. When you assign a user to a company, you create a relation. When you want to unassign, you delete the relation.

Using 404 for resource response that may not exist

I have a RESTful service using HAL links. There is a customer resource and a preferredCard resource. A customer does not always have a preferredCard selected.
As the user must be logged in there is no need to pass customer or card id we will pull it from their identity.
PreferredCard url: GET: <root>/<version>/preferredCard
I think I have two options.
1) Add a preferredCard link on the customer and return a 404 (NotFound) if there is no preferredCard, otherwise return the preferredCard resource.
2) Don't display a link to the preferredCard on the customer if one doesn't exist.
Any thoughts on what is best here. Worried that in the first option I am returning a 4XX when the client didn't really mess up
Thanks
I think you need to handle both situations.
If you know the user has no prefered card, don't give them a link to something that isn't going to work. Maybe give them an alternate link to select one.
Equally, if that URL can exist, the user could always come back to it later, even if it has been removed. In this case, you may want to consider a custom 404 pages. The 404 error would let the user know that the resource they wanted cannot be found, but you can still provide some content, perhaps something explaining what is going on (that there is no current prefered card) and offers some useful links, in this case a link to the page where they can create/select a prefered card.
If there is no preferredCard for the customer-resource, then you may want to serve a createPreferredCard or selectPreferredCard-link instead of just hiding the link to a 404.
This would look like a clean approach to me, since you are hiding stuff that doesn't work, but offer options.