Reputation: 105
I was thinking of how to make a RESTFul API more intention revealing. A common patter I see around various blogs on this is that conventional REST API results in
Ban a Player -> POST /players.
But I were to change to a more intention revealing interface , I could use
Ban a Player -> POST /players/{ playerid }/banPlayer
The second one I feel is more intention revealing.
The common objection I get from the team is that the second one does not comply with start REST style.
Also currently I cannot move away from a RESTful API.
I would like to hear your thoughts on this.
Upvotes: 7
Views: 9476
Reputation: 1329
This Google Cloud article API design: Understanding gRPC, OpenAPI and REST and when to use them clarifies the REST vs RPC debate. REST is more relevant for entity-centric API whereas RPC is more relevant for action-centric API (and CQRS). The most mature REST level 3 with hypermedia controls works well only for entities with simple state models.
Understand and evaluate first the benefits of REST for your case. Many APIs are REST-ish and not RESTful. OpenAPI is actually RPC mapped over and HTTP endpoints but it doesn't prevent it to be widely adopted.
Upvotes: 1
Reputation: 57259
The common objection I get from the team is that the second one does not comply with start REST style.
The easy answer is this: consistency in the API has value, whether REST or not. So "that's not how we do it here" is going to trump "but REST says".
The spelling of URI in an API is a lot like the spelling of method names in your code. There are a lot of different arguments for different styles, but "local convention" is a strong argument by itself.
That said -- REST does not care what spelling you use for your identifiers.
This is what Fielding had to say in 2008
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. Any effort spent describing what methods to use on what URIs of interest should be entirely defined within the scope of the processing rules for a media type (and, in most cases, already defined by existing media types). [Failure here implies that out-of-band information is driving interaction instead of hypertext.]
In band would be including the URI in the representation of the resource -- putting it into the description of a form in the HTML document. Out of band is documenting the URI, and expecting people to do the right thing with it.
Note: there's nothing wrong with human-readable URI, or documenting the URI that should be used. But notice that you can post questions to stackoverflow even though the people who wrote your browser didn't read stack overflow's API documentation -- that's REST.
Upvotes: 1
Reputation: 4700
Since you asked for the RESTful way not the best way, here's my thoughts.
Your RESTful URI options include:
/players
/players/{ playerid }/banPlayer
/player-banning
/entities?action=ban_player&method=PUT
/banana
The RESTful way is to expose knowledge of the next available states purely through hypertext. To do REST, you must use Hypertext As The Engine Of Application State (HATEOAS). Relying on client knowledge of the URI is depending on out-of-band knowledge, which is antithetical to REST.
Your resources do not need to map directly to your business objects. If you choose, you can represent user intent itself as a resource, e.g. a banned player event resource. You can POST to it with some info on which player to ban, and subsequent GETs will provide information on the event.
Oh and just because REST doesn't care what your URIs are, doesn't mean you shouldn't. You'll just have to use a different standard to decide what's best.
Upvotes: 2
Reputation: 12448
With Restful API design there are two schools of thought around how to apply actions
to a resource.
You describe the action to be taken against the resource in the Uri:
Request Uri:
POST /players/{id}/ban
Note: Just use ban
- we already know the resource is a player, its in the base Uri.
You can have the action in the body of the request:
Request Uri:
POST /players/{id}
Request Body:
{ 'action': 'ban' }
You can pick either way - whichever you prefer, there is lots of discussion on both but ultimately both are correct.
Note:
My assumption here that banning a player is more than just updating a part of it, but rather a system action (or state transition) relating to the player. Otherwise if it was just an update to the player resource you should handle with a PATCH or PUT as appropriate.
Some discussions for reference:
With plenty more if you do some Googling...
Upvotes: 13
Reputation: 17683
Long story short: it shouldn't be mandatory to be intention revealing but if you want to add some DDD on how this API looks like then it is nothing that prevents you from doing that
According to HATEOAS constraint of a RESTful web API (this constraint is an essential part of the "uniform interface" feature of REST, as defined in Roy Fielding's doctoral dissertation), the software clients of your API should not care about the URLs. Every possible&permitted action should be included in the response, with the corresponding link relation and URI. In this way you have to hardcode only the link relations.
This constraint does not however prevent you from making the API more intention revealing for the Human clients that try to understand the overall architecture. I recommend you to choose this path, as Human users are at least as important as the software that they write.
Roy Fielding wrote about this on his blog post.
Upvotes: 2
Reputation: 2137
According to the REST API approaches, you need to use your entities in URI, so, as banPlayer
is not an entity, you cannot use it.
I suggest to UPDATE your record with PUT method.
Here you can read more about rules. Actually, the first section about URIs is just about your case.
Upvotes: 1