I'm having some trouble with RPC style verbs starting to appear in my API.
My question is: Is it okay to have these verbs, "Submit", "SendForApproval", "Accept" and "Reject" in a Restful API? Is that going against the Restful principles? What's best practice for naming these Actions?
Our business case:
I have an order. It starts out at status "pre-ordered". I want to then make a call to validate the order against our business logic. Depending on the validation results, I then either submit it or send it for approval. The approval process happens externally to our solution and then when it has been through the approval process the Api is called to mark the order as either Accepted or Rejected.
There is a bit more going on than simply updating statuses - we send things to print queues, spin off tracking documents etc.
So the URI's that we have defined are
https://api.site.com/orders // A list of orders
https://api.site.com/orders/{orderId} // An order
https://api.site.com/orders/{orderId}/ValidationErrors // Get a list of validation results
https://api.site.com/orders/{orderId}/Submit // Submit the order for processing
https://api.site.com/orders/{orderId}/SendForApproval // Send to supervisor
https://api.site.com/orders/{orderId}/Accept // Supervisor Accepts the order for processing
https://api.site.com/orders/{orderId}/Reject // Supervisor can Reject the order
You must avoid inserting verbs in your URIs as much as you possibly can. Furthermore, I disagree with user1438038, because the QueryString filters should be used for search purposes instead of specifying actions.
I believe that there're better approaches to solve this problem. First off, take into account that you shouldn't model your RESTful API in a way that it's highly tied to your business objects (supposing that you're using a OO approach). Moreover, remember that in a REST perspective, everything you expose is a resource rather than objects with its state and behavior.
I'm going to suggest you a different approach but I'm not sure if it's going to fulfill your system requirements but maybe it can be useful to give you some ideas. In your case, you can have multiple resources like PreOrders, Orders, Supervisors...
https://api.site.com/preorders
GET - Display all pre-orders.
POST - Create a new pre-order.
Creating a new order:
https://api.site.com/preorders/1
POST - approves the pre-order. This action's gonna create a new Order.
Displaying all orders that are waiting for approval (by the supervisor with ID=1).
https://api.site.com/supervisors/1/orders
Searching for approved and canceled orders:
https://api.site.com/supervisors/1/orders?status=canceled
https://api.site.com/supervisors/1/orders?status=approved
To cancel or approve an order:
https://api.site.com/supervisors/1/orders/1 (DELETE cancels the order)
https://api.site.com/supervisors/1/orders/1 (POST approves the order)
I'm unsure if it's the best approach to solve your problem but I'm pretty sure it's better than using verbs in your URI.
I'd be fine with that, we are using a very similar setup for order management.
However, another possibility would be passing an action parameter, such as:
https://api.site.com/orders/{orderId}/?action=accept
https://api.site.com/orders/{orderId}/?action=reject
...
The general idea of REST is to have resources (such as order or customer). What you want is more of a RPC semantics, but there is no right or wrong. Your approach is reasonable.
Not is a good practice have verbs in REST uris.
So, if you want change a status in any order, you may send a PUT/POST to https://api.site.com/orders/{orderId} updating only the values you want for your bussines logic.
Related
I have a REST API which serves data from the database to the frontend React app and to Android app.
The API have multiple common endpoints for each model:
- GET /model/<id> to retrieve a single object
- POST /model to create
- PATCH /model/<id> to update a single model
- GET /model to list objects
- DELETE /model/<id> to delete an object
Currently I'm developing an Android app and I find such scheme to make me do many extra requests to the API. For example, each Order object has a user_creator entry. So, if I want to delete all the orders created by specified user I need to
1) List all users GET /user
2) Select the one I need
3) List all orders he created GET /order?user=user_id
4) Select the order I want to delete
5) Delete the order DELETE /order/<id>
I'm wondering whether this will be okay to add several endpoints like GET /order/delete?user=user_id. By doing this I can get rid of action 4 and 5. And all the filtering will be done at the backend. However it seems to me as a bad architecture solution because all the APIs I've used before don't have such methods and all the filtering, sorting and other "beautifying" stuff is usually at the API user side, not the backend.
In your answer please offer a solution that is the best in your opinion for this problem and explain your point of view at least in brief, so I can learn from it
Taking your problem is in isolation:
You have an Order collection and a User collection
User 1..* Orders
You want to delete all orders for a given user ID
I would use the following URI:
// delete all orders for a given user
POST /users/:id/orders/delete
Naturally, this shows the relationship between Users & Orders and is self-explanatory that you are only dealing with orders associated with a particular user. Also, given the operation will result in side-effects on the server then you should POST rather than GET (reading a resource should never change the server). The same logic could be used to create an endpoint for pulling only user orders e.g.
// get all orders for a given user
GET /users/:id/orders
The application domain of HTTP is the transfer of documents over a network. Your "REST API" is a facade that acts like a document store, and performs useful work as a side effect of transferring documents. See Jim Webber (2011).
So the basic idioms are that we post a document, or we send a bunch of edits to an existing document, and the server interprets those changes and does something useful.
So a simple protocol, based on the existing remote authoring semantics, might look like
GET /orders?user=user_id
Make local edits to the representation of that list provided by the server
PUT /orders?user=user_id
The semantics of how to do that are something that needs to be understood by both ends of the exchange. Maybe you remove unwanted items from the list? Maybe there is a status entry for each record in the list, and you change the status from active to expired.
On the web, instead of remote authoring semantics we tend to instead use form submissions. You get a blank form from somewhere, you fill it out yourself, you post it to the indicated inbox, and the person responsible for processing that inbox does the work.
So we load a blank form into our browser, and we make our changes to it, and then we post it to the resource listed in the form.
GET /the-blank-form?user=user_id
Make changes in the form...
POST ????
What should the target-uri be? The web browser doesn't care; it is just going to submit the form to whatever target is specified by the representation it received. One answer might be to send it right back where we got it:
POST /the-blank-form?user=user_id
And that works fine (as long as you manage the metadata correctly). Another possibility is to instead send the changes to the resource you expect to reflect those changes:
POST /orders?user=user_id
and it turns out that works fine too. HTTP has interesting cache invalidation semantics built into the specification, so we can make sure the client's stale copy or the orders collection resource is invalidated by using that same resource as the target of the POST call.
Currently my API satisfies the table from the bottom of the REST, so, any extra endpoint will break it. Will it be fatal or not, that's the question.
No, it will be fine -- just add/extend a POST handler on the appropriate resource to handle the new semantics.
Longer answer: the table in wikipedia is a good representation of common practices; but common practices aren't quite on the mark. Part of the problem is that REST includes a uniform interface. Among other things, that means that all resources understand the same message semantics. The notion of "collection resources" vs "member resources" doesn't exist in REST -- the semantics are the same for both.
Another way of saying this is that a general-purpose component never knows if the resource it is talking to is a collection or a member. All unsafe methods (POST/PUT/PATCH/DELETE/etc) imply invalidation of the representations of the target-uri.
Now POST, as it happens, means "do something that hasn't been standardized" -- see Fielding 2009. It's the method that has the fewest semantic constraints.
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics. -- RFC 7231
It's perfectly fine for a POST handler to branch based on the contents of the request payload; if you see X, create something, if you see Y delete something else. It's analogous to having two different web forms, with different semantics, that submit to the same target resource.
I would like to clarify what'd be the best way of organizing architecture.
I've got rest api and microservices architecture. I have applied the Database per Service pattern.
So let's imagine that the user wants to create an order(an e-commerce system). But users can have a credit limit. So the flow will be as below:
OrderService creates a pending order. Then push an event about it.
UserService processes that event and publishes either a credit limit exceeded event or a credit reserved event.
OrderService receives the event and changes the state of the order to either approved or canceled.
All look good. But the question is what the user will do during this simple flow?
I mean: the user makes a POST request /orders and ...
Web-service awaits until the order gets approved or canceled(includes surely timeout)?
Web-service returns 200 ok and then the user needs to check the order state with some interval?
use web sockets?
something else?
Unfortunately, Any option from above has its advantages and its disadvantages.
The challenge is that I described the simplest case. In reality, tens services(even third party) could be involved. And of course, I am expecting a high load. So the queue may be filled.
Please propose the solution to discuss. I'm greatly appreciating for an answer as well as links to production ready system documentation.
Kudos for a good question. If we look at Saga Pattern, it offers to do ACID like transactions in a distributed system but with some trade-off. One of the trade-offs is Ensuring Rollback if any of the service or entity fails to do what it was supposed to do. This can go even complex if you have more than 5 services completing a Saga. Though it will be a Highly Scalable option if you can orchestrate.
Here I will propose Following,
User Does a POST request for order
OrderService first checks with UserService regarding credit Limit (It can be a REST API call as it might be a simple DB call for UserService)
Then OrderService can act upon based on the return response from UserService
Advantages of this approach
User can see an immediate response
Less Complex to code thus testable and maintainable Code
Disadvantages of this approach
This solution will not be effective if there are too many external (third party) rest api calls
It can introduce single point of failure
The main thing is, all the options will have trade-offs. It is on you to decide which one suits you the best.
According to me
Follow the my rule - Validate First then action
Validate the order before its goes to order service on UI. You can call the userservice api on UI which gives info user can make a order or not.
Step 1. On UI call the userservice API , which validate the user credit limit
Step 2. If validation success or fail
Step 3. Take the action according to step2 result . If success call the order service if not do what you want to do (Call other service etc..)
Advantage
A good user exprience - User get the validation message "you can not make a order your limit is low" or something like that when trying to make the order. Not at the end get a message "You limit is low/or anything"
Less Complexity of code
A more microservice Arch. -
Since your are follow the microservices then if you call the userservice inside the orderservice means orderservice is dependent on it or you can say tightly bound - here your are lossing the benifit of mircroservice arch.
What happen if the userservice is down. The customer cannot make the order or if you change anything in userservice response then you have to change the orderservice also.
What you do if some more validation (to call other service) need in future before making the order.
Redirection Flexibility - Suppose if on fail of validation from userservice then you have to call other service( other independent microservice ) and if you are using the other service inside the orderservice the no of service increases as project grow
Less Request on OrderService - Request goes orderservice only when the validation is passed from the other service or other thing.
So from my point of view
Try to make microservice independent as much possible.
Validate First and action.
A good user exprience
Easy to handle load (if you think)
With all that , now you less dependent on saga.
Its only my opinion - choose what you think best according to your domain
The question is what the user will do during this
simple flow? I mean: the user makes a POST request /orders and ...
You can reply to user the created orderId with status 'pending' while your saga is running. The request should be ended in 200.
How does user get the status?
Push notification, websocket, email, sms. it is up to you to notify the user about the status of event, success, failure, waiting_for_approval.
1. Web-service awaits until the order gets approved or canceled?
2. Web-service returns 200 ok and the user check the order state with some interval?
3. use web sockets?
4. something else?
Not recommended. Saga should be asynchronous. Waiting for reply is synchronous (request/reply style).
This will work, but if your saga is long running, it might be problematic, eg: anything with validation/approval by a human.
This will work assuming you are replying 200 after order creation in pending state, one thing is that you have to make sure your websocket is active, or else, you still have to notify them through email, sms.
Unfortunately, Any option from above has its advantages and its
disadvantages.
You have to choose your poison.
The challenge is that I described the simplest case. In reality, tens
services(even third party) could be involved. And of course, I am
expecting a high load. So the queue may be filled.
Use orchestrated saga (sort like) Netflix conductor, Uber Cadence, Temporal (Similar to Cadence). This will allow you to do something as shown below. At least, easier.
A flow diagram from google shopping api and how they handle it.
Link for more: https://developers.google.com/shopping-content/guides/about-orders
There is little difference in cancelling an order because there was a problem with the credit limit vs. cancelling it because a forklift ran over the package in the logistics facility.
So a relatively simple solution is to reply with an order accepted and status 200 when the order is placed put that in a queue and let the saga run asynchronously. You should provide both an API (and UI) for the user to check the order status and proactively send status updates like billing going through (which is your fist saga) and also other sagas in the order lifecycle
Regarding how to send notifications that depends on the usage scenario (e.g. you can do a callback for a system-to-system integration, but maybe you want to send an email/sms to an end-user etc)
I'm trying to figure out best or common practices for API design.
My concern is basically this:
PUT /users/:id
In my view this endpoint could by used for a wide array of functions.
I would use it to change the user name or profile, but what about ex, resetting a password?
From a "model" point of view, that could be flag, a property of the user, so it would "work" to send a modification.
But I would expect more something like
POST /users/:id/reset_password
But that means that almost for each modification I could create a different endpoint according to the meaning of the modification, i.e
POST /users/:id/enable
POST /users/:id/birthday
...
or even
GET /user/:id/birthday
compared to simply
GET /users/:id
So basically I don't understand when to stop using a single POST/GET and creating instead different endpoints.
It looks to me as a simple matter of choice, I just want to know if there is some standard way of doing this or some guideline. After reading and looking at example I'm still not really sure.
Disclaimer: In a lot of cases, people ask about REST when what they really want is an HTTP compliant RPC design with pretty URLs. In what follows, I'm answering about REST.
In my view this endpoint could by used for a wide array of functions. I would use it to change the user name or profile, but what about ex, resetting a password?
Sure, why not?
I don't understand when to stop using a single POST/GET and creating instead different endpoints.
A really good starting point is Jim Webber's talk Domain Driven Design for RESTful systems.
First key idea - your resources are not your domain model entities. Your REST API is really a facade in front of your domain model, which supports the illusion that you are just a website.
So your resources are analogous to documents that represent information. The URI identifies the document.
Second key idea - that URI is used by clients to cache representations of the resource, so that we don't need to send requests back to the server all the time. Instead, we have built into HTTP a bunch of standard ways for communicating caching meta data from the server to the client.
Critical to that is the rule for cache invalidation: a successful unsafe request invalidates previously cached representations of the same resource (ie, the same URI).
So the general rule is, if the client is going to do something that will modify a resource they have already cached, then we want the modification request to go to that same URI.
Your REST API is a facade to make your domain model look like a web site. So if we think about how we might build a web site to do the same thing, it can give us insights to how we arrange our resources.
So to borrow your example, we might have a web page representation of the user. If we were going to allow the client to modify that page, then we might think through a bunch of use cases (enable, change birthday, change name, reset password). For each of these supported cases, we would have a link to a task-specific form. Each of those forms would have fields allowing the client to describe the change, and a url in the form action to decide where the form gets submitted.
Since what the client is trying to achieve is to modify the profile page itself, we would have each of those forms submit back to the profile page URI, so that the client would know to invalidate the previously cached representations if the request were successful.
So your resource identifiers might look like:
/users/:id
/users/:id/forms/enable
/users/:id/forms/changeName
/users/:id/forms/changeBirthday
/users/:id/forms/resetPassword
Where each of the forms submits its information to /users/:id.
That does mean, in your implementation, you are probably going to end up with a lot of different requests routed to the same handler, and so you may need to disambiguate them there.
I'm working on a REST API and my tickets collection has multiple ways to be updated since it will go through multiple status. Note that some of those status can only be performed by a specific role (RBCA). With that in mind, what would be the best approach?
1) Using sub-methods for the specific actions
PATCH /tickets/:id/validate
PATCH /tickets/:id/update
PATCH /tickets/:id/finish
2) Control what is updated based on the current status of the ticket and the user's role with a single PATCH /tickets/:id
Which one is the best when it comes to the REST best practices?
Which one is the best when it comes to the REST best practices?
Short answer: choice #2.
Longer answer: the reason we care which identifier is used as the target of an request, is that HTTP has cache invalidation semantics built into the protocol: if you successfully patch a resource, the generic components involved know to evict all of the cached representations of that resource. See Invalidation in RFC 7234.
So if we were implementing a web site, and trying to take advantage of cache invalidation, we might have a hierarchy like
# the readable link to a specific tickets collection
/tickets/:id
# a validation form that submits data to /tickets/:id
/tickets/:id/validation
# an update form that submits data to /tickets/:id
/tickets/:id/update
# a finish form that submits data to /tickets/:id
/tickets/:id/finish
So our workflow to "update" the tickets collection might look like...
GET /tickets/:id
GET /tickets/:id/update
POST /tickets/:id
In an API where we aren't restricted by HTML, we could consider using unsafe methods other than POST to do the work.
Note: this does means that the "POST/PATCH" end point in our implementation would need to do additional routing of its own to reach the validation/update/finish logic. With forms, that would mean using the submitted data to determine which behavior is intended -- perhaps a hidden field, or maybe the endpoint just makes a guess based on which keys are in the form data.
quick question - I was reading about RESTful services yesterday and someone had asked why SOAP wasn't RESTful. The answer was that SOAP doesn't have the 'generality of interfaces' property as is required by REST.
Then it struck me that I had been adding custom routes to my Web API like so:
Custom Routing with ASP.NET Web API
By doing that - I made my web API non-generic, thereby making the service non-RESTful, right? Not that that's a big deal, I just want to know whether I grasped the concepts correctly.
Well the rest rqeuires you to identify resoruces alone, not actions on them.
For example you might have an action addComment on Person, your route being
POST persons/2/addComment
This would make it non restful. The ideal way to do this would be:
POST persons/2/comments
For deleting a comment DELETE persons/2/comments/{commebntid}
So if you vary from this, your service becomes non restful. Its pretty hard to make a completely restful interface.
For example, if you have an object account, that you directly increment or decrement balance
accounts/2. You might have withdraw and deposit actions. POST accoints/2/withdraw. In rest, you need to either pass the balance as a parameter after decrementing it (PUT). There may be cases where you donot want to do this. You might not want to let the world know the balance of the user. Then you cant easily use put. You'd have to create a new entity: transaction and create transactions and calculate the account balance on the basis of transactions.
Ther eis no such thing as a generic API. You can't use amazons api and facebooks api interchangibly since the entities and operations are different. Don't worry too much about generalization. Just understand what the RESTful way is, and see if you can implemen it. If you have to tweak around it a bit, that's fine