Why should I make my service Restful when the business needs and workflows are complicated? - rest

My service requirements and business workflows are bit complicated. First, please consider the two different options below.
In my case, the problems going with restful option are
In the restful option, basically to distinguish the operation intended, I
need to inspect the input payload. So, my controller logic is going to bit ugly.
For each of these operation, I need to check for specific roles and permissions. Based on the input payload, I need to check whether the user has the required permission first, rather than having it at the controller method level as we do now in the RPS style.
For some operations, I need to check the current status of the order. For example, approving or rejecting an order which is currently in draft status doesn't make sense. Before approving and disapproving, the order should be in pending for approval status. So, I need call DB to check the current status and this will impact the performance.
Monitoring and perf profiling are going to very complex with restful option in my case.
Trouble shooting production issues going to be complex. Because the input
payload needs to logged and inspected. The http verbs needs to be inspected.
I don't think restful way is making it simple just because of exposing fewer endpoints. Now, clients of this service has to be given clear documentation
explaining what input they have send in order to perform a specific
intended action.
My service is not a simple content delivery applications with fewer operation. In the future, I may need to support more operations than what I have today.
Please don't tell me, I can pass the operation to be performed in the request header. I don't think, it solves all of the above problems.
So, now why should I bother making my service restful?

Related

Using GET verb to update in rest api?

I know the use of http verbs is based on standard specification. But my question if I use "GET" for update operations and write a code logic to update, does it create issues in any scenario? Apart from the standard, what else could be the reason to use these verbs for a specific purpose only?
my question if I use "GET" for update operations and write a code logic to update, does it create issues in any scenario?
Yes.
A simple example - suppose the network between the client and the server is unreliable; specifically, for a time, HTTP responses are being lost. A general purpose component (like a web proxy) might time out, and then, noticing that the method token of the request is GET, resend the request a second/third/fourth time, with your server performing its update on every GET request.
Let us further assume that these multiple update operations lead to an undesirable outcome; where do we properly affix blame?
Second example: you send someone a copy of the link to the update operation, so that they can send you a request at the appropriate time. But suppose you send that link to them in an email, and the email client recognizes the uri and (as a performance optimization) pre-fetches the link, triggering your update operation too early. Where do we properly affix the blame?
HTTP does not attempt to require the results of a GET to be safe. What it does is require that the semantics of the operation be safe, and therefore it is a fault of the implementation, not the interface or the user of that interface, if anything happens as a result that causes loss of property -- Fielding, 2002
In these, and other examples, blame is correctly affixed to your server, because GET has a standardized meaning which include the constraint that the semantics of the request are safe.
That's not to say that you can't have side effects when handling a GET request; "hit counters" are almost as old as the web itself. You have a lot of freedom in your implementation; so long as you respect the uniform interface, there won't be too much trouble.
Experience report: one of our internal tools uses GET requests to trigger scheduling; in our carefully controlled context (which is not web scale), we get away with it, and have for a very long time.
To borrow your language, there are certainly scenarios that would give us problems; but given our controls we manage to avoid them.
I wouldn't like our chances, though, if requests started coming in from outside of our carefully controlled context.
I think it's a decent question. You're asking a hypothetical: is there any value to doing the right other than that's we agree to use GET for fetching? e.g.: is there value beyond the fact that it's 'semantically nice'. A similar question in HTML might be: "Is it ok to use a <div> with an onclick instead of a <button>? (the answer is no).
There certainly is. Clients, servers and intermediates all change their behavior depending on what method is used. Even if your server can process GET for updates, and you build a client that uses this, your browser might still get confused.
If you are interested in this subject, don't ask on a forum; read the spec. The HTTP specification tells you what clients, servers and proxies should do when they encounter certain methods, statuses and headers.
Start at RFC7231

Does this break the statelessness of a RESTful API?

Take this design of an API:
/articles/{id} - Returns an article. Client provides a token in the header to identify them.
/updated-articles - Returns collection of articles that have been updated since the client's last call to this endpoint, and only includes articles that this client previously requested. Client provides a token in the header to identify them.
The second enpoint doesn't fit very well with me. The design motivation of that second enpoint is that the client does not need to track the time of their last requests. Is this breaking the "statelessness" constraint of RESTful APIs? An alternative approach would be /updated-articles?since=YYYY-MM-DD but this would require clients to remember
Your "token" is basically a client id, and the fact of remembering the date of their last access is keeping a client-state on the server.
Think about it : If you had to scale up your service, could you simply plug-in a new server, copy your service's files, and redirect via a round-robin algorithm on one or another of the two server (without having them sharing informations) ? Clearly no, because you would need your table tokens<->date of last consultation shared between the two servers. So no it's definitely not stateless.
Plus, I don't understand your point :
An alternative approach would be /updated-articles?since=YYYY-MM-DD
but this would require clients to remember
Wouldn't a token require a client to remember ? On the contrary, this way would be RESTful, since the client-state (the date of last consultation) would be kept on the client side.
Basically, no, I don't think your second resource would break statelessness.
I think it's okay to have your client's keep track of their own 'updated at' time stamp. Your api should be stateless. The client doesn't have to be stateless.
If anything the client should retain a lot of state. The client will be a device central to one user and their specific needs. It's responsible for keeping track of the user's needs and current state. In this situation someone will have to store that time stamp. I think it should be your clients, not your server.
This is just my opinion though.
I did find a write up over the true meaning of statelessness that I think could benefit you as well here.
We should avoid creating endpoints with no related entity. So instead of /updated-articles?since=<timestamp> a better approach should be:
/articles?updated=true&since-last-request=true or
/articles?updated-since-last-request=true
If the intended result should affect all clients. Meaning every request time stamp must be kept on the server. Or
/articles?updated-since=<timestamp>
If the intended result depends on each client behavior. That seems to be your case.
The choice between the former or the latter (or both) depends on the use case. But the main point is to avoid creating endpoints with no related entity and having special cases being defined by parameters.
As a guideline:
Endpoints are substantives, adjectives are parameters and verbs are the HTTP request methods
This also means a simple 'GET /articles' means returning ALL articles. To avoid abuse you may issue proper 4xx codes depending on the case.

REST Business Logic and error handling

I am trying to make a REST application where I try to hide to hide Business Logic from request and responses.
I have to examples which I don't know how to handle.
First example: I have a shopping cart and product x can't be ordered with product y. The client however decided to order them both. How can I give a proper error message or guide the client that this isn't allowed. Because giving an error saying "x and y are not allowed together" seems like exposing Business Logic to me.
The structure is in place because of different services that we have. The products can be re-used, but the order intake is different. For example we can offer an order intake for vehicles which need different configuration when ordering cloths. In both cases you will have product, which have name and price and therefore can be re-used. That's is why vehicles and cloths can't be ordered together and shouldn't. To make this more user friendly there will be a service which presents available options for the specific order intake. But there should be a part which validates it and gives proper error on this.
Second example: A client has one pending order and can't create a new order when the pending order is completed. This seems/feels stateful to me and should probably avoided. How should this be handled?
UPDATE So resolving the issue for my first example could be to create an endpoint something like /products?type=vehicle or /products/combinations?type=vehicle. This is for displaying the allowed products/combinations and have an endpoint /order to put the products in where the validation happens. These endpoints can stand on their own, but the context may come from somewhere else. Do I understand correctly?
As the other answer already pointed out, this is only marginally related to REST, it has I think more to do with the meaning of "exposing business logic" and "statelessness".
The first point of not wanting to expose business logic: It is only exposing business logic if some system really needs to interpret the specific error. If it is "only" supplying a localized message to the user, it is not exposing any logic to the systems in between. The frontend system does not need to know what is going on, it only needs to display the message from the backend system.
There are cases when the frontend system needs to know, to be able to guide the user. It is not fundamentally wrong to expose business logic, as long as it is not implicitly exposed, but explicitly part of the interface description.
On the second point about statelessness: REST defines that the communication needs to be stateless. That means any arbitrary request from client should be meaningful without the context of any previous messages (this includes previous logins, sessions, whatever). Each request stands on its own. This does not mean that specific resources can not keep a state of their own. A shopping cart on the backend does in fact has a state, this is OK.
Or said differently: Can the next request hit a different server and still be successful? And I mean without session replication, distributed cache or other magic. If yes, the communication is stateless. If you need "sticky" sessions or such things, then no, you are not stateless.
I think your questions are not entirely related to REST itself but I will try to answer them anyways. Maybe, you can give more details about what bothers you reading my answers.
I am not completely sure how the first question is related to REST because I feel it is about wording. The question to me would be: Why is it not allowed to order both of these products together? So, you cannot but them into the same shopping basket? This would not be really user-friendly, so the best idea would be to allow it. If you cannot change that both are not allowed at the same time, I would just "grey out" all the items that are not allowed together with product X if it is already in the shopping basket.
However, this is more of a user experience question. Maybe, you could go into detail here in what exact case a user could be insert both of the products at the same time, while it is not allowed.
Towards your second question: In most online shops you usually have a state that is either mapped to the account, a session or via cookies. If you truly want to have a stateless API here with REST, you could work with order IDs. These could be passed to each request. Of course, the order itself has a state. But the requests do not have one.
Notice: REST does not mean much. You basically have no state for each request and have all information in the URL that are necessary.
Maybe, this helps a bit already.

Using Rest to trigger remote procedures

I am working on an application that is primarily concerned with polling data from a third party, then mapping and persisting relevant information to a customer. It does this on a fixed interval, but the requirements also specify a way to manually fire off the process. This manual call will only receive a status on the execution of the process, but is not interested in the data created by the process.
I implemented the call using http, but my implementation has been identified as not RESTful. Having now done the research into what better than means, I completely concur as I was using the URI to define verbs instead of nouns.
Is it possible to make this RESTful? Is it okay to make a resource that is extremely transient, like this?
POST /rpc/{process}?param1=....&....
Or should the process itself be considered permanent, but the triggering of as a temporary update? I doubt this as this is not an idempotent action.
PUT /rpc/{process}?run=true&param1......
Is there a correct way to handle this and be called RESTful? If it is not, do I use SOAP or continue to use the simple http structure and live with the fact that it is not RESTful?
Use querystrings for filtering
POST/PUT depends on what you want your process to do (PUT for idempotent actions, POST for non idempotent actions).
Keep it simple and I do not see any issues the way you have resolved this.

Transactions in REST?

I'm wondering how you'd implement the following use-case in REST. Is it even possible to do without compromising the conceptual model?
Read or update multiple resources within the scope of a single transaction. For example, transfer $100 from Bob's bank account into John's account.
As far as I can tell, the only way to implement this is by cheating. You could POST to the resource associated with either John or Bob and carry out the entire operation using a single transaction. As far as I'm concerned this breaks the REST architecture because you're essentially tunneling an RPC call through POST instead of really operating on individual resources.
Consider a RESTful shopping basket scenario. The shopping basket is conceptually your transaction wrapper. In the same way that you can add multiple items to a shopping basket and then submit that basket to process the order, you can add Bob's account entry to the transaction wrapper and then Bill's account entry to the wrapper. When all the pieces are in place then you can POST/PUT the transaction wrapper with all the component pieces.
There are a few important cases that aren't answered by this question, which I think is too bad, because it has a high ranking on Google for the search terms :-)
Specifically, a nice propertly would be: If you POST twice (because some cache hiccupped in the intermediate) you should not transfer the amount twice.
To get to this, you create a transaction as an object. This could contain all the data you know already, and put the transaction in a pending state.
POST /transfer/txn
{"source":"john's account", "destination":"bob's account", "amount":10}
{"id":"/transfer/txn/12345", "state":"pending", "source":...}
Once you have this transaction, you can commit it, something like:
PUT /transfer/txn/12345
{"id":"/transfer/txn/12345", "state":"committed", ...}
{"id":"/transfer/txn/12345", "state":"committed", ...}
Note that multiple puts don't matter at this point; even a GET on the txn would return the current state. Specifically, the second PUT would detect that the first was already in the appropriate state, and just return it -- or, if you try to put it into the "rolledback" state after it's already in "committed" state, you would get an error, and the actual committed transaction back.
As long as you talk to a single database, or a database with an integrated transaction monitor, this mechanism will actually work just fine. You might additionally introduce time-outs for transactions, which you could even express using Expires headers if you wanted to.
In REST terms, resources are nouns that can be acted on with CRUD (create/read/update/delete) verbs. Since there is no "transfer money" verb, we need to define a "transaction" resource that can be acted upon with CRUD. Here's an example in HTTP+POX. First step is to CREATE (HTTP POST method) a new empty transaction:
POST /transaction
This returns a transaction ID, e.g. "1234" and according URL "/transaction/1234". Note that firing this POST multiple times will not create the same transaction with multiple IDs and also avoids introduction of a "pending" state. Also, POST can't always be idempotent (a REST requirement), so it's generally good practice to minimize data in POSTs.
You could leave the generation of a transaction ID up to the client. In this case, you would POST /transaction/1234 to create transaction "1234" and the server would return an error if it already existed. In the error response, the server could return a currently unused ID with an appropriate URL. It's not a good idea to query the server for a new ID with a GET method, since GET should never alter server state, and creating/reserving a new ID would alter server state.
Next up, we UPDATE (PUT HTTP method) the transaction with all data, implicitly committing it:
PUT /transaction/1234
<transaction>
<from>/account/john</from>
<to>/account/bob</to>
<amount>100</amount>
</transaction>
If a transaction with ID "1234" has been PUT before, the server gives an error response, otherwise an OK response and a URL to view the completed transaction.
NB: in /account/john , "john" should really be John's unique account number.
Great question, REST is mostly explained with database-like examples, where something is stored, updated, retrieved, deleted. There are few examples like this one, where the server is supposed to process the data in some way. I don't think Roy Fielding included any in his thesis, which was based on http after all.
But he does talk about "representational state transfer" as a state machine, with links moving to the next state. In this way, the documents (the representations) keep track of the client state, instead of the server having to do it. In this way, there is no client state, only state in terms of which link you are on.
I've been thinking about this, and it seems to me reasonable that to get the server to process something for you, when you upload, the server would automatically create related resources, and give you the links to them (in fact, it wouldn't need to automatically create them: it could just tell you the links, and it only create them when and if you follow them - lazy creation). And to also give you links to create new related resources - a related resource has the same URI but is longer (adds a suffix). For example:
You upload (POST) the representation of the concept of a transaction with all the information. This looks just like a RPC call, but it's really creating the "proposed transaction resource". e.g URI: /transaction
Glitches will cause multiple such resources to be created, each with a different URI.
The server's response states the created resource's URI, its representation - this includes the link (URI) to create the related resource of a new "committed transaction resource". Other related resources are the link to delete the proposed transaction. These are states in the state-machine, which the client can follow. Logically, these are part of the resource that has been created on the server, beyond the information the client supplied. e.g URIs: /transaction/1234/proposed, /transaction/1234/committed
You POST to the link to create the "committed transaction resource", which creates that resource, changing the state of the server (the balances of the two accounts)**. By its nature, this resource can only be created once, and can't be updated. Therefore, glitches committing many transactions can't occur.
You can GET those two resources, to see what their state is. Assuming that a POST can change other resources, the proposal would now be flagged as "committed" (or perhaps, not available at all).
This is similar to how webpages operate, with the final webpage saying "are you sure you want to do this?" That final webpage is itself a representation of the state of the transaction, which includes a link to go to the next state. Not just financial transactions; also (eg) preview then commit on wikipedia. I guess the distinction in REST is that each stage in the sequence of states has an explicit name (its URI).
In real-life transactions/sales, there are often different physical documents for different stages of a transaction (proposal, purchase order, receipt etc). Even more for buying a house, with settlement etc.
OTOH This feels like playing with semantics to me; I'm uncomfortable with the nominalization of converting verbs into nouns to make it RESTful, "because it uses nouns (URIs) instead of verbs (RPC calls)". i.e. the noun "committed transaction resource" instead of the verb "commit this transaction". I guess one advantage of nominalization is you can refer to the resource by name, instead of needing to specify it in some other way (such as maintaining session state, so you know what "this" transaction is...)
But the important question is: What are the benefits of this approach? i.e. In what way is this REST-style better than RPC-style? Is a technique that's great for webpages also helpful for processing information, beyond store/retrieve/update/delete? I think that the key benefit of REST is scalability; one aspect of that is not needing to maintain client state explicitly (but making it implicit in the URI of the resource, and the next states as links in its representation). In that sense it helps. Perhaps this helps in layering/pipelining too? OTOH only the one user will look at their specific transaction, so there's no advantage in caching it so others can read it, the big win for http.
I've drifted away from this topic for 10 years. Coming back, I can't believe the religion masquerading as science that you wade into when you google rest+reliable. The confusion is mythic.
I would divide this broad question into three:
Downstream services. Any web service you develop will have downstream services that you use, and whose transaction syntax you have no choice but to follow. You should try and hide all this from users of your service, and make sure all parts of your operation succeed or fail as a group, then return this result to your users.
Your services. Clients want unambiguous outcomes to web-service calls, and the usual REST pattern of making POST, PUT or DELETE requests directly on substantive resources strikes me as a poor, and easily improved, way of providing this certainty. If you care about reliability, you need to identify action requests. This id can be a guid created on the client, or a seed value from a relational DB on the server, it doesn't matter. For server generated ID's, use a 'preflight' request-response to exchange the id of the action. If this request fails or half succeeds, no problem, the client just repeats the request. Unused ids do no harm.This is important because it lets all subsequent requests be fully idempotent, in the sense that if they are repeated n times they return the same result and cause nothing further to happen. The server stores all responses against the action id, and if it sees the same request, it replays the same response. A fuller treatment of the pattern is in this google doc. The doc suggests an implementation that, I believe(!), broadly follows REST principals. Experts will surely tell me how it violates others. This pattern can be usefully employed for any unsafe call to your web-service, whether or not there are downstream transactions involved.
Integration of your service into "transactions" controlled by upstream services. In the context of web-services, full ACID transactions are considered as usually not worth the effort, but you can greatly help consumers of your service by providing cancel and/or confirm links in your confirmation response, and thus achieve transactions by compensation.
Your requirement is a fundamental one. Don't let people tell you your solution is not kosher. Judge their architectures in the light of how well, and how simply, they address your problem.
If you stand back to summarize the discussion here, it's pretty clear that REST is not appropriate for many APIs, particularly when the client-server interaction is inherently stateful, as it is with non-trivial transactions. Why jump through all the hoops suggested, for client and server both, in order to pedantically follow some principle that doesn't fit the problem? A better principle is to give the client the easiest, most natural, productive way to compose with the application.
In summary, if you're really doing a lot of transactions (types, not instances) in your application, you really shouldn't be creating a RESTful API.
You'd have to roll your own "transaction id" type of tx management. So it would be 4 calls:
http://service/transaction (some sort of tx request)
http://service/bankaccount/bob (give tx id)
http://service/bankaccount/john (give tx id)
http://service/transaction (request to commit)
You'd have to handle the storing of the actions in a DB (if load balanced) or in memory or such, then handling commit, rollback, timeout.
Not really a RESTful day in the park.
First of all transferring money is nothing that you can not do in a single resource call. The action you want to do is sending money. So you add a money transfer resource to the account of the sender.
POST: accounts/alice, new Transfer {target:"BOB", abmount:100, currency:"CHF"}.
Done. You do not need to know that this is a transaction that must be atomic etc. You just transfer money aka. send money from A to B.
But for the rare cases here a general solution:
If you want to do something very complex involving many resources in a defined context with a lot of restrictions that actually cross the what vs. why barrier (business vs. implementation knowledge) you need to transfer state. Since REST should be stateless you as a client need to transfer the state around.
If you transfer state you need to hide the information inside from the client. The client should not know internal information only needed by the implementation but does not carry information relevant in terms of business. If those information have no business value the state should be encrypted and a metaphor like token, pass or something need to be used.
This way one can pass internal state around and using encryption and signing the system can be still be secure and sound. Finding the right abstraction for the client why he passes around state information is something that is up to the design and architecture.
The real solution:
Remember REST is talking HTTP and HTTP comes with the concept of using cookies. Those cookies are often forgotten when people talk about REST API and workflows and interactions spanning multiple resources or requests.
Remember what is written in the Wikipedia about HTTP cookies:
Cookies were designed to be a reliable mechanism for websites to remember stateful information (such as items in a shopping cart) or to record the user's browsing activity (including clicking particular buttons, logging in, or recording which pages were visited by the user as far back as months or years ago).
So basically if you need to pass on state, use a cookie. It is designed for exactly the very same reason, it is HTTP and therefore it is compatible to REST by design :).
The better solution:
If you talk about a client performing a workflow involving multiple requests you usually talk about protocol. Every form of protocol comes with a set of preconditions for each potential step like perform step A before you can do B.
This is natural but exposing protocol to clients makes everything more complex. In order to avoid it just think what we do when we have to do complex interactions and things in the real world... . We use an Agent.
Using the Agent metaphor you can provide a resource that can perform all necessary steps for you and store the actual assignment / instructions it is acting upon in its list (so we can use POST on the agent or an 'agency').
A complex example:
Buying a house:
You need to prove your credibility (like providing your police record entries), you need to ensure financial details, you need to buy the actual house using a lawyer and a trusted third party storing the funds, verify that the house now belongs to you and add the buying stuff to your tax records etc. (just as an example, some steps may be wrong or whatever).
These steps might take several days to be completed, some can be done in parallel etc.
In order to do this, you just give the agent the task buy house like:
POST: agency.com/ { task: "buy house", target:"link:toHouse", credibilities:"IamMe"}.
Done. The agency sends you back a reference to you that you can use to see and track the status of this job and the rest is done automatically by the agents of the agency.
Think about a bug tracker for instance. Basically you report the bug and can use the bug id to check whats going on. You can even use a service to listen to changes of this resource. Mission Done.
You must not use server side transactions in REST.
One of the REST contraints:
Stateless
The client–server communication is further constrained by no client context being stored on the server between requests. Each request from any client contains all of the information necessary to service the request, and any session state is held in the client.
The only RESTful way is to create a transaction redo log and put it into the client state. With the requests the client sends the redo log and the server redoes the transaction and
rolls the transaction back but provides a new transaction redo log (one step further)
or finally complete the transaction.
But maybe it's simpler to use a server session based technology which supports server side transactions.
I think that in this case it is totally acceptable to break the pure theory of REST in this situation. In any case, I don't think there is anything actually in REST that says you can't touch dependent objects in business cases that require it.
I really think it's not worth the extra hoops you would jump through to create a custom transaction manager, when you could just leverage the database to do it.
In the simple case (without distributed resources), you could consider the transaction as a resource, where the act of creating it attains the end objective.
So, to transfer between <url-base>/account/a and <url-base>/account/b, you could post the following to <url-base>/transfer.
<transfer>
<from><url-base>/account/a</from>
<to><url-base>/account/b</to>
<amount>50</amount>
</transfer>
This would create a new transfer resource and return the new url of the transfer - for example <url-base>/transfer/256.
At the moment of successful post, then, the 'real' transaction is carried out on the server, and the amount removed from one account and added to another.
This, however, doesn't cover a distributed transaction (if, say 'a' is held at one bank behind one service, and 'b' is held at another bank behind another service) - other than to say "try to phrase all operations in ways that don't require distributed transactions".
I believe that would be the case of using a unique identifier generated on the client to ensure that the connection hiccup not imply in an duplicity saved by the API.
I think using a client generated GUID field along with the transfer object and ensuring that the same GUID was not reinserted again would be a simpler solution to the bank transfer matter.
Do not know about more complex scenarios, such as multiple airline ticket booking or micro architectures.
I found a paper about the subject, relating the experiences of dealing with the transaction atomicity in RESTful services.
I guess you could include the TAN in the URL/resource:
PUT /transaction to get the ID (e.g. "1")
[PUT, GET, POST, whatever] /1/account/bob
[PUT, GET, POST, whatever] /1/account/bill
DELETE /transaction with ID 1
Just an idea.