6

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.

Quality Catalyst
  • 6,531
  • 8
  • 38
  • 62
Indu
  • 95
  • 2
  • 8
  • 2
    REST doesn't care about URI designs at all as it is just a technique to decouple clients from servers and clients should not attempt to extract knowledge from an URI as this might break if the server changes the URI at some point. Instead both, client(s) and API, should make use of relation names and supports special media types that express certain semantics. A media type is just a plain text description of a syntax and its semantics of data to exchange. – Roman Vottner Jan 07 '18 at 21:29
  • How about (slightly facetious) `BAN /players/{playerid} HTTP/3` – Darragh Mar 04 '19 at 23:36
  • Except with the tag and title, I think you forgot to mention how CQRS has any play in this. – istepaniuk Oct 16 '20 at 15:21

6 Answers6

10

With Restful API design there are two schools of thought around how to apply actions to a resource.

  1. 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.

  2. 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...

shenku
  • 11,969
  • 12
  • 64
  • 118
  • 3
    Consider using `PATCH` instead of `POST` and I'll upvote. – Quality Catalyst Jan 07 '18 at 22:13
  • 2
    @QualityCatalyst my assumption here that banning a player is more than just updating a part of it, but rather a system action relating to the player. Otherwise I would agree and you would also get rid of the `ban` Uri part all together. – shenku Jan 08 '18 at 00:54
  • Discussions for reference include: http://restful-api-design.readthedocs.io/en/latest/methods.html, https://github.com/interagent/http-api-design/issues/58, https://nordicapis.com/designing-a-true-rest-state-machine/, https://softwareengineering.stackexchange.com/questions/141410/restful-state-changing-actions – shenku Jan 08 '18 at 03:21
  • The rest way would be considering the "banning" a resource. So the first approach is the right one. The second, on the other hand looks like RPC style which goes against Restful philosophy – caeus Feb 23 '18 at 10:26
  • 1
    I agree with @Quality Catalyst . This should be a PATCH and it should only use the approach number 2. The PATCH document should be included in the request body. PATCH supports operations (actions) that change state. Your operation is 'ban'. This is consistent with REST. – Yuli Bonner Oct 11 '19 at 12:46
  • @Evert this is exactly what controller resources are made for. RPC calls focused REST resources – Yassin Hajaj Jan 27 '21 at 22:03
  • In my opinion, only the first approach is valid – Yassin Hajaj Jan 27 '21 at 22:04
2

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.

Constantin Galbenu
  • 16,951
  • 3
  • 38
  • 54
2

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
  • anything else, REST doesn't dictate what your URIs should look like

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.

Eva
  • 4,397
  • 5
  • 43
  • 65
1

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.

Yevhenii Herasymchuk
  • 2,047
  • 15
  • 20
1

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.

VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
0

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.

Digital Stoic
  • 1,229
  • 11
  • 20