I have been reading about how resources should be modeled after nouns and how related resources should be represented in the URI.
Short background:
Let us say that I have to create a document for a person. The person data exists in an external application but we need to create documents in our application. The starting point for a document creation is to perform a search on person which will fetch the details of person from an external application and then we will create/save the details of both the document and the person in our database.I feel that in this case Person is a noun and hence a Resource irrespective of whether our application creates a new person or not.Even if the operation is not directly creating a new person it seems like document cannot exist without a person. So the create Documents URI should be a
POST /persons/personId/documents
which is more intuitive.
But there is a different suggestion that person is not really a resource here, the argument being that we are not modifying Person and hence the URI should be
/documents
So my questions:
Would be be right to say that Person is not a resource based on the arguement above ?
Isn't the first approach better/more intuitive for creating a document: /persons/personId/documents? The fact that a document will be created for a Person and a document cannot be created without a Person as such.
There are a lot of misconceptions about REST, and people often engage in endless discussion about something that isn't really a problem in REST.
First, URI semantics are irrelevant in REST, so forget the noun/verb nonsense. I've seen people stressed out trying to figure out how to convert an action to a noun and an HTTP verb, and that's absolutely pointless. In REST, the whole URI is an atomic identifier, and the URI contents don't matter, only what is identified by the URI. Sure, we should put some effort on having clear and well-organized URIs, that clearly communicate the intent to the developer, but that's just a general good practice, not a REST constraint. There's no such thing as RESTful URI. What makes an URI RESTful is how you obtain it, not how it looks like.
Second, URI semantics are irrelevant because REST APIs must be hypertext driven. Related resources should be represented by links in the resource representation itself, not in the URI, as your first phrase says. How your clients know the URI to create documents? Are they reading something like /persons/<personid>/documents in documentation and replacing personid with a value? Is that what you do when you join StackOverflow and want to read your questions? You check documentation for an URI template, get your user id, paste that into the URI placeholder? Of course not. You simply follow a link and you don't really care about what exactly the URI is. That's how REST works. Like the Web itself.
So, when your clients enter your API, they can have a root document which shows the representation of the Person resource associated with them and permanent link to that, and links to related resources, including documents. The documentation for the Person resource can explain how the rel=documents link points to a collection of Document resources associated with that person, and how POST'ing to that same URI creates a new Document resource. As you can see, what you are asking isn't really a problem in REST, because the "intuitive" thing to do is to follow a link. It can be /persons/<personid>/documents or anything else. What matters is how your client obtains those links.
Third, everything identified by an URI is a resource, and everything you are interacting with should have at least one URI. That means if you are interacting with something identified by anything other than an URI -- for instance, you are sending an id in the body --, and that thing you are interacting with is not reachable through an URI, then it's not a resource and you are doing something wrong.
So, in case the answer is not clear:
If you have an URI for Person, it's a resource. If you don't, it's not.
The only RESTful approach is to follow links, and the URI semantics won't matter. The more descriptive the URI is, the better, of course, but that's up to you, and not a REST constraint.
It does not matter where a Person is stored. You are designing an API which by definition is an interface that abstracts from storage backends.
The URL you propose is very RESTful since it correctly models the relatinship between person and document. In addition, this URL scheme has a segment for the collection resource of all persons (/persons) and one for the collection of all documents that belong to a document (/persons/{personId}/documents).
As long as you don't allow request like
POST /persons
or
PUT /person/{personId}
which would create a new person or alter an existing one, I can see no problem with this approach.
I would say Person is a resource because it is possible to request information about a particular person: the documents they own.
Indeed to me it seems perfectly reasonable for URIs to express relationships between different resources.
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.
We have a design where a user has access to products, but only in a certain category.
A superuser can list all products in all categories with a simple GET request, such as GET /products.
Simple filtering already exists via the query string, so the superuser can already restrict his search to category N by requesting GET /products?category=N.
Say that user X is authenticated, and user X has access to products with category of 3.
Should an API server:
mandate that the user pass the filter for the appropriate category -- ie require GET /products?filter=3, and GET /products would fail with 403 Forbidden? -- or
expect a simple GET /products and silently filter the results to those that the user is authorized to access?
expect a simple GET /products and silently filter the results to those that the user is authorized to access?
Changing the representation of a resource depending on which user is looking at it strikes me was a Bad Idea [tm].
Consider, for instance, the use case where a uri gets shared between two users. They each navigate to the "same" resource, but get back representations of two different entites.
Remember - here's what Fielding had to say about resources
The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time.
Now, there are conceptual mappings which depend on the perspective of the user (e.g. "today's weather in my city"). But I'm a lot more comfortable addressing those by delegating the work to another resource (Moved Temporarily to "today's weather in Camelot") than I am in treating the authorization credentials as a hidden part of the resource identifier.
If consumers of your api are arriving at this resource by following a link, then 403 Forbidden on the unfiltered spelling is fine. On the other hand, if consumers are supposed to be bookmarking this URI, then implementing it as a redirecting dispatcher may make more sense.
The redirecting approach is consistent with remarks made by Fielding in a conversation about content negotiation on the rest-discuss list in 2006
In general, I avoid content negotiation without redirects like the
plague because of its effect on caching.
E.g., if you follow a link to
http://www.day.com/
then the site will redirect according to the user's preference to one of
http://www.day.com/site/en/index.html
http://www.day.com/site/de/index.html
Both of the solutions are perfectly valid. You can always hide things when the user does not have the permission to see them. This means, that you can display a filtered representation of /products by the actual user, or you can hide the /products resource and give link only to the /products?filter=3 resource. I don't think there is a best practice here, since both solutions are easy to implement.
#VoiceOfUnreason:
Apparently you did not read Fielding's work carefully enough.
Changing the representation of a resource depending on which user is
looking at it strikes me was a Bad Idea [tm].
The representation depends on the whole request, not just on the GET /resource part. The Authorization header is part of the HTTP request as well. So changing the representation depending on the Authorization header is valid in REST. It is just the same as changing the representation depending on the Accept header. Or do you say that we should serve XML even if somebody requests for JSON? It is a huge mistake to think that a single resource can have only a single representation. Another mistake to return a broken link to the client and let them waste resources by sending pointless HTTP messages...
Consider, for instance, the use case where a uri gets shared between
two users. They each navigate to the "same" resource, but get back
representations of two different entites.
REST is for machine to machine communication and not for human to machine communication! The browser is not a REST client. Or did you mean that a facebook bot will share the link with a google crawler? Such a nonsense...
Let's say I have a domain with customers that can "commit" (which is a use case in the domain). Is it preferable to include the actor (customer) explicitly in the resource like this:
POST /customers/{id}/commit
or would it be better to model the creation of a new commit like this:
POST /commitments
Does it matter and if so, why?
It depends on the relationship between customer and commitment. A Rest-ful URI should be exposing a resource. If commitments make sense only in the customer context (or are a part of the customer) then an URI like this one is justified (it is the same as yours, the customer is the main resource, but note it is not using a verb, but noun, which is preferable):
POST /customers/{customer_id}/commitments
But if the resource is logically dependent on another resource (different than customer) or can also be used out of the context of customers (for example a box of commitments) or it can be used by itself, it would make more sense to design the URI around said resource e.g.:
POST /commitmentbox/commitments
or just
POST /commitments
I'd suggest the Creating resources section in this blog post. It discusses multiple best practices in REST-ful URI design. Also see this one where an even more complex scenario is discussed (customer makes orders that have line items). Both posts are very good.
Good luck!
We have 2 developers who have conflicts in the way to design the RESTful API Endpoint. Basically, let say that we have Facebook product in hand, one table for the posts.
First developer give the opinions that
We should seperate Endpoint by product, not by the technical storage. To be like that, we will have endpoint for user facebook post and other facebook post.
/v1/wall/mypost
/v1/wall/other
To be like that, we be able to configure each products that may return difference results
Second developer disagree, give the opinions that
If be like that, it will make infinite endpoint. it will have /wall/someone, /wall/sometwo.
We should have single endpoint, and just let that be a part of query. ex. /wall?user=someone, /wall?user=sometwo
The endpoint should be look like technical schema, it return the same result, why it have to seperated to make it more jobs on maintenance the code.
What is the good practice to design our endpoint? Is it should be endpoint by the product? or is it should be by schema?
It should depend on what 'resource' that the service is suppose to manage from the API user perspective and not from the internal implementation.
With that, if the service is to manage say, a resource that can be identified by 'someone', 'sometwo' and, then the correct way to model it is
/wall/someone/
/wall/sometwo/
In this case, 'someone' and 'sometwo' are two different resources and you could have infinite # of them; but that has nothing to do with the internal storage or implementation.
On the backend, there should be some url pattern to extract 'someone' and 'sometwo' as resource and map them into internal implementation details.
What are these "endpoints" you speak of? That's SOAP terminology! RESTful web services are defined in terms of "resources" that are uniquely identified by URL.
A resource typically represents an entity in your domain model (e.g., a user). The ID of the entity is typically used as a path element ("path parameter" in the lingo of most REST libraries, such as JAX-RS) in the URL. Query parameters should only be used to sort/filter results on the server side.
Your first developer is closer to being correct.
I'm currently figuring out a way how to build our REST webservice so resources can be linked to other resources at creation time. Take the following scenario.
We have /user/123/ who sits in the collection /company/456/users/ and also in the global users collection at /user/123/
When I want to add a new user to company 456 I perform a POST to /company/456/users/ to add it to this collection. But what if the user resource depends on more than only the company? Lets say for example that the user resource also tracks address information on the user so it might also depend on the /country/12/ resource. How can I pass the dependency on the country to the REST webservice. Should I just pass a country_id in the payload of the POST request?
What is considered best-practice for the RESTful approach to managing links to other resources?
Ummm... posting to /company/456/users/ does not look right to me...
What about posting to /users, or even better to /user/{newid}?
From there, you can either just create a user, and maybe add links in another moment, or you can specify all the links as url-encoded parameters (or in the payload, but I prefer the former... it just looks cleaner to me, but this is only my personal opinion):
POST /users?company_id=456&county_id=12
or
POST /users?company_id=456
or
POST /users