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.
Related
In my current API design I'm following these rules:
PATCH is used to partially update a resource
POST is used to create resources
PUT isn't used at all
I need to expose specific update actions (not exposed as PATCH, for security reasons), i.e. change the status of an order to "confirmed", "partially confirmed" or "refused".
I'm struggling on:
POST /carts/:id/:status and DELETE /carts/:id/:status: seems wrong as POST should create resources
PATCH /carts/:id/:status: seems wrong because the payload would be empty
Which one would be the most consistent and appropriate with the above API design? Do I have other options?
It may help to review Webber 2011
You have to learn to use HTTP to trigger business activity as a side effect of moving documents around the network.
I need to expose specific update actions (not exposed as PATCH, for security reasons), i.e. change the status of an order to "confirmed", "partially confirmed" or "refused".
How would you do this on the Web?
The most common answer would look something like this: you would have a web page for "the order"; and that page would include hyperlinks to some forms - it might be a simple "change order status form", or you might have different forms for each change. When we submit the form, the browser would create from form data and metadata an HTTP POST request, targeting whatever resource was specified by the form.
Important takeaways
It is okay to use POST.
The server can choose whatever URI it likes as the form target.
One convenient choice would be to use the URI for "the order" web page, because that allows you to take advantage of the general purpose cache invalidation defined by the HTTP standard.
You can, of course, use PUT or PATCH semantics instead, if you like. The primary difference is that these methods use remote authoring semantics - they are the HTTP methods we would use if we were trying to edit a web page.
To change the status of an order, it might go roughly like this: you would GET the current web page, and edit your local copy to change the status information. Then you would use HTTP to save your copy of the web page on the server:
For PUT, the payload of the request would be the entire web page with your edits.
For PATCH, the payload of the request would be a patch document describing just your edits.
The server would then need to either accept your request (applying your changes to its copy of the web page) or reject them (for example, if those changes are not consistent with business policy).
Which one would be the most consistent and appropriate with the above API design? Do I have other options?
You'll probably have an easier time if you relax the restriction that POST is only used to create resources.
Remember, the world wide web is the reference implementation of the REST architectural style, and it was catastrophically successful. Yet PUT and PATCH were used only rarely -- almost all information was carried to web servers using POST semantics.
But if must limit yourself to these rules for non technical reasons, then you might consider a resource model where information is sent to the business by creating new resources on the web server. In other words, instead of changing the status of the order by editing the order web page, you could instead create a new "change the status of the order" document on the server.
(Technically, you could use any of POST/PUT/PATCH to create the new document, but POST is normal and consistent with your constraints, so it seems a reasonable starting point).
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.
As I understand it, a HTTP GET request should return the requested data and is considered RESTful if safe (read-only) and idempotent (no side effects).
However, I would like to implement a service to show new items since last visit using an URI of /items/userid/new, can that in any way be RESTful?
When returning the data, the items sent in response to the GET request should be marked as read in order to keep track of what is new. Marking these items will violate both the safe requirement and the idempotent requirement.
Does that mean .../new is never considered RESTful?
Very interesting question. I think the answer would be "depends on the implementation" since there are different solutions that would all meet the business requirement.
If every visit to the URL /items/userid/new by the same user modifies the DB records, then it's not a "safe method" and would not fit the commonly accepted REST pattern.
If you're filtering for the new items on the view, but without any corresponding DB changes with each GET call, then it would certainly be RESTful. For example:
/items/userid/new?lastvisit=2015-12-31
or
/items/userid/new?last_id=12345
or storing the list of viewed items on the client side would certainly qualify.
Normally we decide the restful service and associate protocol methods to it. In case of HTTP it is we use GET,POST,PUT...etc. Normally Get is used get some application state that will rendered with hyper text.
Here /items/userid/new can be new service that returns the list. Any modification on this list will be subsequent request with different method association.
Keeping track of already visited items should not be the server's responsibility. The client should rember already visited items. That leads to better scalability and loosy coupled systems as the server must not handle these parameters for e.g. thousand of clients.
To deliver fresh items you could, as Cahit already touched, provide a feed that includes all items for either a time frame or a fixed number of items. Generally an archived feed is a good choice.
As a result of this a client can crawl your feed on its own to retrieve all new items.
Interesting question indeed.
For a plain url, I would not do it. One reason for example: I remember sending a testmail with a unique link pointing to our own webserver. While passing through the ISP's mailserver, a request was made with that url to our server.. This was done by a spamfilter to check if the url existed.. So, if a mail was sent to the customer saying 'look here for the new items', those would be gone even before the mail was received.
And you certainly wouldn't want that plain url to appear in search results somewhere, or be used for preloading pages.
On the other hand, if the request was made during login (or using a cookie), it could be ok.
Maybe that's what SO does when we view our statistics/responses.
I would like to record user actions on my website, not only on POST requests, but on GET requests as well. For example, suppose the user tries to search for a city with the following GET request:
/search_city?name=greenville
This request would return a list of cities with the name "greenville". I'd also like to save this keyword to the server, as the "search history" for a user. I'm planning to just do the save this information during the processing of the GET call.
Is this a violation to RESTful principles? If yes, how do I do this the right way?
I see this kind of audit logging as an invisible side-effect. If the next person to call
/search_city?name=greenville
still gets the same answer then your GET is valid. A similar case would be some kind of cache building, the caller of GET doesn't (need to) know that you're doing some extra work.
Focus on the formal API - send this request get this response.
If there's some resource available in the API where the user search history is available, then it's not OK to do that, since your GET request has a visible side-effect. For instance, a client caching responses is under no obligation to know that any resource changed because he did a GET request to anything else. I think the only way to do this and stay compliant is to explicitly mark the side-effected resource as uncacheable.
In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe". This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.
Naturally, it is not possible to ensure that the server does not generate side-effects as a result of performing a GET request; in fact, some dynamic resources consider that a feature. The important distinction here is that the user did not request the side-effects, so therefore cannot be held accountable for them.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
If that's kept only for internal usage, I guess it's fine to do it that way, but I still recommend against it.
Is it appropriate to perform actions with REST, other than simple create (POST), read (GET), update (PUT), and delete (DELETE)? I'm kind of new to the whole RESTful theology, so bear with me, but how should I accomplish the following:
I have a web service that needs to talk to another web service. Web service A needs to "reserve" an object on Web service B. This object has a timeout of validity, but can be deleted immediately if need be. It's essentially a glorified permissions system which requires web services to reserve a space on web service B before taking any actions.
My initial thought was to 1. enable authentication of some sort, 2. in the serverside response to a GET call, reserve the space and return the result, and 3. provide immediate "unreservation" of the object via a DELETE call. Is this still being RESTful?
Yes, it's OK to perform actions with rest. What matters is that these actions should be guided by the representations you exchange.
If you think about the way the web works (via a browser), you do this all the time: you get an HTML form that lets you choose a number of actions you can perform. Then, you submit the form (typically via POST) and the action is performed.
It's good to be able to use DELETE via a programmatic client (which is something that non-AJAX requests in browsers wouldn't support), but the overall approach of a RESTful system should be very similar to what you find for websites (i.e. the focus should be on the representations: the equivalent of web pages in your system).
GET shouldn't have side effects, so don't use GET to make the reservation itself, use something like POST instead.
No - unlikely to be restful
From your description ...
2. in the serverside response to a GET call, reserve the space and return the result
GETs should be idempotent. For this reason alone, your service is unlikely to be restful because the state of the system after the first GET is different.
You really need to consider that a Reservation is a resource and should be created with a POST to a reservations container which will return the URI of the new resource in the Location header of the HTTP response. This UrI can be used by Get to return the resource and updated with a PUT
Post should be used to extend an existing resource and Put for replacing the state of a resource. In your case, consider the Post to be updating a list of Reservations and returning the URI of the new resource (not just the I'd). Put can be used for changing the state associated with the resource identified by the UR
You're on the right track, but your reservation of the object should be with a PUT; you're PUTting a reservation on the object, i.e. changing the underlying object.
PUT is the right verb here, since you know what resource you're modifying, and it should be idempotent for multiple requests.