top of page
Rechercher

No rest 4 REST - #2 - Should we put an operation (an action, a step of the lifecycle) as a suffix ?

  • lionelmazurie
  • 29 août 2021
  • 6 min de lecture

When writing a corporate set of API guidelines, one of the most difficult parts to fix is based on the fact of considering the prohibition of operations in the resource path. It can be really required because the couple HTTP verb + resources shouldn’t be sufficient enough when the functional reason can be too much different and specific not to be taken into account inside the path.


By default, without these types of “must not” rules, teams and developers are sometimes putting a “create” in a POST or a “search” in the path for a GET which is a kind of duplication and a quasi-nonsense. Indeed, for a level 2 of the Richardson’s Maturity Model, focussed on HTTP verbs, it can be really avoided. As proof, major API guideline authors like ZALANDO require (by a MUST’s rule) to keep URLs free from the use of explicit operation inside the path by a typed new object with a PUT for instance.


For me it is an open door not to be adherent with a corporate ontology of official and a transverse data model / metamodel. Rapidly endpoint will be out of control that is lowering the quality of the API products exposed. It is why the dynamic model of an “object” should be modelled (by a classical UML diagram or a BPML format, for instance) to determinate if whether or not there is explicit operations to be taken into account.


If obviously omitted for a POST, a GET and a DELETE, the case of the operation PUT (same for PATCH) is then more delicate. We cannot use the same “static” path with a stateless resource to pilot several treatments that are modifying deeply the resource and collateral objects then doesn’t only consist in a change of properties ... And above all, it is easier, for the developer, to quickly find the right endpoint.


A POST is mainly dedicated to the creation of a resource from scratch, then including an explicit operation for that is a complete non-sense. When a POST is used for a complex GET requiring data in the input body payload, again, it could be indicated by an operation in the top of this payload. In this case it is then necessary to implement a switch by the API Manager to point at the right backend different web services dedicated. Then in this case an operation could be added when the API Manager is not used as a router.


Example:

POST … / retail-formats / {formatId} / products to create a product without forcing an id that is then allocated by the system (otherwise a PUT is usually used)


POST … / retail-formats / {formatId} / products / {gtin} / searching-competitors for a quite complex search when a GET is not possible by a specific resource path and a query-params (due to a large number of criteria). With a specific path like that a one-to-one association with a backend webservice with a request body payload will be possible. The operation must be explicit enough with an action and a direct object attached (here we are searching for the competitors ...). The only difference with a POST with an id or not is for us not sufficient enough.


Note that personally I am a fan of a spinal-case form rather than snake_case just for aesthetic reasons for the path but lowerCamelCase for identifiers.


For a GET it is better to include it in the query params by a tag “operation=product-substitution” or an “action=product-recommendation”, here for common operation possible in a retail product to be fixed by an unequivocal guideline rule.


For a DELETE the basic action is clear and the id of the object or of the group of objects is put in the resource path when for this HTTP verb both a query-params and an input body payload are forbidden.


But again, the PUT (or the PATCH really scarce in expositions from our daily feedback from operational various API catalogs) oversees the complete real life of the objects, of the resources, between creation and deletion it is why it is very hard not to include an operation in the path.

In addition, it is important to expose from the very first “v1” all necessary endpoints to cover all the operations of the known lifecycles of the resources involved inside the API. Sometimes it can be just a declaration in the specification without having the webservice connected but just a mock tool to handle it.


Avoiding the addition of an operation by creating a different resource path is unnatural when the added object in the path is not relevant to be really included in the metamodel. It would be just a circumvention indeed.


So, a resource path with only static objects without action or operation is tough to handle with. A query-params according to the protocol is forbidden too in both a PUT or a PATCH. Put in the input body payload a verb to be interpreted / handled by the API Manager is sometimes a complex operation (very often not considered in a corporate API doctrine because of a doctrinal choice of technical architects) with the necessity to have a switch to point at different REST web services in the back end.


But personally, we prefer a non-alignment between exposition and backends in general for these main three reasons:


- Let free the backend developers and their ability to integrate rapidly outside / remote available webservices (SaaS ones in particular) designed according to the own vendor API guidelines or without any minimum prerequisites very often ...


- Let them free for their own webservices even with a gap with corporate rules of design (permanently not advised, but necessary sometimes for a very high agility …).


- Having a complete freedom for the design of the exposed facade API where guideline rules can be fully applied and respected. This is generating very high-level stores with an excellent corporate image.


So, after several years of practice, we prefer to authorize the use of an operation in the resource path for the PUT and only for the PUT.


Example:

PUT… / retail-formats / {formatId} / catalogs / {catalogId} / products / {gtin} / decommissioning.

For this “major” functional operation, it is not just changing a property of the object, here the product, but it has a real action designed in the lifecycle of this object. Again, if it just changes of one or several properties linked with this operation, the lack of an operation is preferred. Here a decommissioning is a real action that can call a specific dedicate web service or even a microservice with an adapted choreography or orchestration of services for this aspect of context.


For a pure aesthetic point of view, we prefer a form present and continuous instead of infinitive or a passive way (then a “decommissioning” instead of a “decommissioned” or a “decommission”).


Here, in order according to the piece of metamodel, for a specific corporate retail format (supermarket, local store, digital, …), for a specific typed catalog and then for a catalogued product defined (by its universal code GS1’s GTIN for example), we want to apply a complex change that is not a change of several properties on the product.


But again, for a simple change of a status of this product in the catalogue (for example a status to be set to “on sale”!) both a PUT and a PATCH can be used without an operation because we are just changing an intrinsic property of it:


PATCH … / catalogs / {catalogId} / products / {productId} with the new value of the status inside the input body payload.


We are thinking it is the best solution to be shared and exposed in corporate guidelines in order to remove all uncertainties for Product Owners and API designers, developers and outsourcers that must respect these rules.


As a conclusion, let us put no explicit operations in the resource path except for an action that is not just a change of properties of these resources, but the call of a specific service in the backend dedicated to operating on the change not linked with the creation or the true deletion of the resource.

Indeed, when an API Manager is implemented as a real router, even for a PUT, the operation can be avoided in the path and even forbidden by adding a clause like “action=” for example, set at the top of the request body payload … then the spirit of REST is more respected to manage just both explicit and implicit stateless resources …


Speculative next potential coming topics to approach new tough API use cases:


#3 – The DELETE paradigm at the “Big Data Age” and for a set of objects to be erased …


#4 – A well-design of the resource path and management of identifiers in the resource paths


#5 – For a use of the aliases “me”, “my”, “all”, “some”, “one” instead of an identifier in the resource path to use a non-official one, to secure information submitted or to manage a collection of ids pushed inside the body request ...

 
 
 

Comments


© 2020 by Lionel Mazurié

bottom of page