Link to home
Start Free TrialLog in
Avatar of MarianoSB
MarianoSB

asked on

RESTFul API - actions that don't fit into the world of CRUD operations

Hi Experts,

I would like to know about practical experiences, from developers using RESTFul Api, and the way you've solved the problem of non Crud operations.
Im currently reading some interesting posts:
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
http://stackoverflow.com/questions/21794744/how-to-design-rest-api-for-non-crud-commands-like-activate-and-deactivate-of-a
http://restful-api-design.readthedocs.io/en/latest/methods.html
https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling

It would be great to know about applied solutions to this kind of problem.
Best regards, and please excuse my english.
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

What is the question?  Please tell us what you want to do, what you've tried and what difficulty you have experienced, thanks.
SOLUTION
Avatar of Olaf Doschke
Olaf Doschke
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Just by the way: You find other ideas than CRUD, too. like BREAD (browse, read, edit, add, delete).

I'd propose ABCD (add, browse, change, delete) if it's about data APIs only. But if you want an extensible model, then you rather look for a service like implementation as ODATA is. ODATA is very complex and sites saying the offer an ODATA API most often only implement it partial. You could pick ideas from that, but don't call it ODATA, if you don't implement a full blown ODATA interface to your resources.

Bye, Olaf.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
It also depends on your resources and operations.  On shared hosting you will not usually be allowed to use PUT and DELETE.  I have quite a few operations where I upload/download data and/or files using POST over HTTPS.  It is much simpler than a formal REST API but it gets the job done.  And of course, I don't have to 'publish' an API because me and my customers (thru my software) are the only ones using them.
>My view is that the basic CRUD operations are sufficient, because what we are taking about is the VERBs which are going to act on DATA.

If it's data, yes.

If you use a RESTful approach to control objects like the infamous coffee machine the first public webcam showed, then you don't need CRUD operations on that. A resource can be anything, it's not necessarily data,

I think you know better, because of how detailed you talk about such APIs you show a deep knowledge, but you most probably never have used REST for anything else but maintaining and serving data.

I suggest the read of http://codebetter.com/iancooper/2011/07/15/why-crud-might-be-what-they-want-but-may-not-be-what-they-need/

As database applications developers we tend to think in the box of data lifecycles. As you can model anything in data you can act on things like data, but I think this article hits a nerve about how crude the CRUD operations thinking has become. It's stupid to force everything into this box of CRUD operations. That's wrong.

Bye, Olaf.
I think you're going over the top, Olaf, because the question is about designing a RESTful API for electronic use. As the author of your quoted link says :-

We need to drop the focus on CRUD and move to a focus on tasks: what is it that the user wants to accomplish, and how can we help them accomplish that?

You are perfectly correct in stating that I have never used REST for anything else than serving up data. It's horses for courses and for serving up and maintaining the integrity of data REST is, in my opinion, ideal, providing of course, one does not go to extreme lengths to squeeze everything into one paradigm. (See my comments on HTTP entities). JSON is a boon, previously I have used XML.

But I think some of the comments on that paper are very relevant, Dimitri :
I think you missed the point that CRUD is a common denominator for DB model, not for business requirements.

Here read for DB model the data model. Then Keith Cromm :
Get with the program, man!  "CRUD" is soooooo yester-decade(s)!
Go contemporary with "iMAD", the synonym acronym of CRUD.iMAD keeps in step with everything starting with "i" these days.

see what I mean with horses for courses?  And then Chris Hayes :
I think what he means by CRUD is form based systems.

Now who on earth would have dreamt that up?

Rentrons a nos moutons. We are discussing a RESTful API, not an application nor a form based system. An API to be used by program developers and as such the simpler and more consistent it is the better.
Well, but what is MarianoSB specifically asking about?

problem of non Crud operations

So seems you're the one concentrating on the thing not asked for, BigRat.

Bye, Olaf.
Let me break down what I said and why:

My first post
1. I addressed CRUD to say it can be sufficient fo data centric APIs
That was addressing the possible misconception CRUD may not be enough, if this API merely is about data anyway, it could still be enough.
2. Next two paragraphs I am addressing that REST ≠ CRUD and that you could just use the two most commonly used and allowed http verbs of GET and POST to make a RESTful API making much more operations on whatever the URIs should represent.
3. I finish this thought pointing out ODATA has this in the form of the equivalent to a WSDL description of a web service via meta data.

To expand on this source in the direction of an answer: The core API URL pattern therefore could be baseServiceURI/resourceURI/operation?parameters and the operation is rather part of the URI than specified via the http verb used. I'd still suggest reading access via GET and write/change/delete access via POST, but as  Dave correctly says you might not be able to define or use all verbs and are limited to what your hoster allows.

My second post:
4. As you rambled about CRUD only I pointed you to this article. Thanks for your thoughts on this, that's very much appreciated. I think the question for asking about non CRUD operations shows a thought in the direction of needing a more user and workflow oriented API. You could argue the role of the RESTful API is not the application logic but a mere communication protocol, but OData contradicts that simplification, it's defining itself as a Protocol for REST APIs and while - as the name suggests - OData itself is very data centric the extended and general ideas of it also go in other directions.

Over the top? Well, the question is about the NON crud aspects, so that is an article giving food for thought for both people only thinking in the CRUD schema and people seeing the need for something on top of it. Just because Mariano didn't specified what else but CRUD operations he thought of, is no reason to say this article is over the top. It's going in the same direction and I second the thought about more than just CRUD operations in an API.

Bye, Olaf.
Avatar of MarianoSB
MarianoSB

ASKER

Dear experts.
First of all, sorry for the delay, I am always traveling and siting down and try to write decent English takes me a long time. Thank you very much for taking the time to comment on my question.
Although I am currently using REST, the question of how to address the problems of conceptualizing resources that are not specific activities CRUD on data (tables), for example:

-Login
-Logout
-Print A document

Other examples might that can be "mapped" to table actions, but i think could fit into a specific resource

-Transfer of funds (a transfer Resource?)
-Cancel A reservation (a Cancel resource?)
-Pay An invoice (a Payment Resource)

In addition, maybe the fact that using tools like ngresource angular https://docs.angularjs.org/api/ngResource/service/$resource) or the tools provided by Yii (http://www.yiiframework.com/doc-2.0/guide-rest-quick-start.html) that I assume were designed mainly to manage tables, brings me more confusing than clarity.
So far I resolve different types of queries about resources, using a parameter and a switch in the controller that receives the request, and despite having improved in some aspects, such as the fact of having defined resources mapped to multiple tables (maybe a seller persisted in person and seller tables), and representing business objects, i have not conceived the way to think of a resource, for example of the type DocumentPrint.

Would it be okay to think of a resource REST Login / Logut? And others presented above? Is there any opensource softare that you know (no matter the progr language) that is exemplary in the context of the question?
Your contributions have been invaluable, thank you very much and again my apologies for the delay.
Best regards,

Mariano
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
What sort of API are we designing? Is it an open API like that of Facebook or Google and co, or is it an API which you are going to use from Angular?

Because if it is like that of Facebook, squeezing all the functions into a REST CRUD type interface is going to be difficult. You're going to have to jump through hoops. I'd stick to the types of functions they use rather than reinvent the wheel.

On the other hand if it is a REST interface for Angular then I'd advise a couple of things.

First for Login/Logout I'd use Satellizer and a three tier approach. The Web/Mobile side would be Angular but all "services" communicate through a Node/Express server which forwards requests to the database, does the authentication, and serves up static resources. I do not store user passwords in the database, nor do I use that what the user gives in to access the database. This is simply because if the user is cracked, I loose database integrity. I send a registered user and a password each time from node/express to the database for the transaction. The database is on the same cluster/LAN as the node server. I also use challenge access with SHA rather than plain password even over https and allow users to login via Facebook and co (OAuth2). I am also using JW Tokens with limited lifetime. With this structure I don't have security issues with my Angular Apps.

You raise an interesting point in regard to payment procedures. A proper ledger only ever writes. You write debits for services rendered and credits for payment. Cancelling a debit results in a credit (actually a voucher rather than real money) and cancelling a credit results in a debit (a storno). Thus the only CRUD operation is C for create.
Dear Experts,

I am very grateful for your contributions, each of you comment open to me a new door to learning.
It's true what Olaf mentioned, I'm not an architect. Unfortunately I was not lucky enough to have formal training, and I had a long road of self-education, with many potholes that formal education would have prevented.
For several years I am walking, slowly, the path of continuous improvement, incorporating tools and knowledge that will enable me to evole to better systems, not only in technology but in architecture, but I know i have much to learn.
In response to your question BigRat, the system that I am developing, has a frontend entirely made with html5 and angular, a backend management made in PHP (Yii) that does not have me drawbacks, and api rest that is providing the data to the frontend (perhaps in this design is where I have to think differently)
As far as I planned, the frontend in angular, communicates only with the rest api, it is a system like so many, data management, you might compare it to an human resources management system.
In this scenario, there are common problems such as login, logut, printing, reservations, cancellations, and that's where I wanted to improve my design api, because I feel I have to improve my understanding of the design of the rest apis. I could define URIs for specific actions (in fact to login and logut did), but I did not want to miss the opportunity to continue learning or at least reflecting on my usual practice.
Is basically evaluate if design as Olaf mentioned, that resources that have operations, which resemble a RPC (right?), Or a design where everything (including printing) is a resource. On the web there is a lot of material, many questions and answers, holding both positions, and my intention was simply to bring to this space the question , and to learn from your discussions and reflections.

Here I present some comments that have brought me to consult here

- from here: http://stackoverflow.com/questions/9719693/exposing-operations-on-resources-restfully-overloaded-post-vs-put-vs-control

Exposing processes as resources is a commonly-encountered recommendation in RESTful design conversations. In RESTful Web Services (O'Reilly) the authors suggest "if you're tempted to expose complex objects or processes through overloaded POST, try giving the objects or processes their own URIs, and exposing them as resources". In RESTful Web Services Cookbook (O'Reilly), in recipe 2.6, the author says "Designate a controller resource for each distinct operation". In REST In Practice (also O'Reilly) the author describes a coffee shop system with a Order resource accepting POSTs

- from here: http://restful-api-design.readthedocs.io/en/latest/methods.html
(note the exception detail)

Sometimes, it is required to expose an operation in the API that inherently is non RESTful. One example of such an operation is where you want to introduce a state change for a resource, but there are multiple ways in which the same final state can be achieved, and those ways actually differ in a significant but non-observable side-effect. Some may say such transitions are bad API design, but not having to model all state can greatly simplify an API. A great example of this is the difference between a “power off” and a “shutdown” of a virtual machine. Both will lead to a vm resource in the “DOWN” state. However, these operations are quite different.

As a solution to such non-RESTful operations, an “actions” sub-collection can be used on a resource. Actions are basically RPC-like messages to a resource to perform a certain operation. The “actions” sub-collection can be seen as a command queue to which new action can be POSTed, that are then executed by the API. Each action resource that is POSTed, should have a “type” attribute that indicates the type of action to be performed, and can have arbitrary other attributes that parameterize the operation.

It should be noted that actions should only be used as an exception, when there’s a good reason that an operation cannot be mapped to one of the standard RESTful methods. If an API has too many actions, then that’s an indication that either it was designed with an RPC viewpoint rather than using RESTful principles, or that the API in question is naturally a better fit for an RPC type model.

From the recomendation of Olaf, I was looking into tweeter and there are, by example:

https://dev.twitter.com/rest/reference/post/account/update_profile

There, I can't realize to understand, update_profile is a resource? or an operation ?

I'm not trying to reject any of your comments, just trying to learn, a little step on in the path of good software.

Thank you very much again for your time, I'll be waiting to hear about your thoughts to finish this question.
Best regards,
I haven't had the time to full read, but in regard of the twitter example you found: The resource URI is only up to account, update_Profile is an operation/action on this resource. The full URL would contain the desired output format, eg json ...update_profile.json, which indicates the response format to the update_profile operation. Twitter API is NOT a simple CRUD API, which you can see from it only using the POST and GET verbs. But it is still a RESTful API, it has defined its own rules of the URI schema, different from a strict/classic CRUD RestfulAPI and different from ODATA. Proprietary. As you intend to do. Anyway it's a good example of how complex you can go with simple URI requests.

In a pure CRUD approach you'd have the URI https://dev.twitter.com/rest/reference/post/account/ you'd use a PUT or PATCH request and the data changes will be written to the request body in some format, To get the updated account you'd then do a GET request. Twitter has solved this in a much more convenient way. RESTful APIs are not a DIN or ISO norm. Unless you have to apply to any more concrete standard, as for example Angulars rules for an API, you're very free to define your way of URI pattern. Just ensure you will know what part of the URI is a resource and what not.

If you think you need actions depending on the resource, then that's what you can implement, as simple as that. http://baseURI/resource/action could be your pattern, and that might be specifically http://api.yourdomain.com/v1 as base URI for version 1 of your RESTful API, continued with /user/:id for a certain user - where :id might be a int id, uuid or user nickname and finally /login for the action. The verb login could be specific only to user resources.

The idea of CRUD removes actions from the URI, it only has the four actions create, read, update and delete. And that comes from thinking or resources as being records of table of a database. And records only have these four main actions. Everything else just is interpretation of the data. What is a resource then still is mainly defined by the database structure, the entities of the database are resources. Every action mainly is UPDATE of some resource. CREATE only is needed to create a new resource, the birth, DELETE is only needed to delete it, the death of it and READ is reading current state. So the main operations are READ and UPDATE and every real world action you think of has to be done with some combination of reads and updates of several resources. In this model an order shipping is neither a resouce, nor a single operation, you need to update several products and reduce their stock and you need to update the order items and order as shipped. The API itself is easier to implement, the real world operations you think of have to be broken donw into many of the atomic basic CRUD operations. Both approaches have their pros and cons.

Bye, Olaf.
The Twitter API only uses GET and POST since they are always implemented in any system which makes a web access. They don't even use DELETE. In fact the API is loosely based on a URL in two parts resource/operation, like POST statuses/destroy:id. Notice the number of deprecated URLs as the system has grown.

There is nothing wrong with this approach. In fact they probably started off with the resource/operation idea from the beginning but over the years have strayed away a bit.

If an API has too many actions, then that’s an indication that either it was designed with an RPC viewpoint rather than using RESTful principles, or that the API in question is naturally a better fit for an RPC type model.

I'm not sure what they means by an "RPC Model"? I remember when Don Box came up with SOAP, which was meant to be a protocol for a simple object model. The idea that you basically have a class which has methods and SOAP allows you to call those methods with HTTP as if it were a sort of universal marshalling mechanism (Don came from Microsofts DCOM). I have never seen a simple SOAP system in operation. They all seem to be generating Java classes and heaps of boilerplate code - a bit like the Enterprise Beans people.

I don't know how PHP works, but I suspect that a URL corresponds effectively to a script (In the system which I maintain a URL corresponds directly to a Ratscript file), so sending DELETE or PUT or POST or GET will have to result in handling all of those cases in the script - which I would have preferred to do using individual scripts.

In my current system I don't use an application server anymore (Ratscript ran on a sort of TomCat server) since most of the logic has moved to Angular. I use Node/Express to serve to the browser (instead of Apache and a connector) and re-route the REST calls to the database. Some calls from Angular are handled in Node, and some Node scripts make REST calls onto the databases. Since I do the authentication in Node, I don't have to worry about users accessing my main database, where all the sensitive information resides.
Thank you for yor comments.
Best regards,

Mariano