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
Related
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 want to follow the best practice to implement a REST API. There is a resource I want to expose and I can think of two ways of doing it as an endpoint.
I want to give the user the opportunity to receive all the payments for a certain campaign.
I can expose /campaigns/{id}/payment that returns a paginated list of payments with all the data for each (name, address, date...). Where /campaign/{id} in turn returns all the data of the campaign (name, description..., array of paymentId with a route to get them one by one).
Or I can expose /payments/campaigns/{campaignsId}.
What is the best approach and why?
I would use /campaigns/{id}/payments because it communicates the contents of the response that the client can expect when querying this URL with a GET most clearly and according to common practice.
GET /camapaigns/{id}/payments
reads much like "give me all the payments for the campaign with id = {id}". So this follows the principle of least astonishment. Also, the client then gets exactly what's requested.
There's a nice API design guide for RESTful APIs from Microsoft, if you'd like to read more about this.
Assuming that REST cares about the URI spelling is a misconception.
However, I encourage you to adopt a consistent naming convention in URIs for your API. It's a common approach to use use plural nouns for URIs that reference collections and organize the URI to represent a hierarchy.
So, for the situation you've described in your question, you could use /campaigns/{id}/payments for identifying your resource. It identifies a collection of payments for a particular campaign.
I have Users collection which is accessible in '/users'. It has implemented with CRUD. My question is, for registering a new user, do I really need to create URL '/register'? Basically it violates Restful concept (register is a verb) but I tempt to since I need to do something else.
Use
POST /users
with a User representation in the body to register a user.
In general, a POST to a collection resource is used to create a new resource in the collection.
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.
Philosophically, I had questions about some examples on how to tackle the following REST scenarios:
1) A user who is signed in wants to 'favorite' someone's blog posting. The user id is a guid and the blog posting is a guid. Should this be a PUT because user/blog exist, or POST because there is no entry in the 'favorites' table?
2) A security row in the DB consists of 10+ properties, but I'd only want to update one part of the entity (# of failed login attempts for a user). What should the call be? Pass the entire data transfer object in JSON? Or just add a new api route for the specific action to update? I.e. a PUT with just one parameter (the # of login attempts) and pass the id of the user.
3) Similar to #2, a user class (consisting of 25+ properties) but I'd only like the user to update a specific part of the class, not the whole thing. Philosophically do I need to pass the entire user object over? Or is it OK to just update one thing. It seems I could get crazy and make lots of specific calls for specific properties, but the reality is I will probably only update 2-3 specific parts of the user (as well as obviously updating the whole thing in other cases). What's the approach here for updating specific parts of an entity in the DB?
Thanks so much
Use a POST if you don't have an ID/UUID yet.
The resource is the security record. Do a PUT on that ID, and pass a block of the properties to be changed.
Ditto (2). You should get whatever parameters will help you identify that record in the DB. If it's unsavory to send these in the POST request and you're doing AJAX, just stash them in the session.
With REST, everything is about updating discrete resources ("nouns"). It's up to you how you want to assign these, but a simple interface that uses verbs ("PUT", "GET", "DELETE", etc..) sensibly, returns relevant HTTP codes, and is easy for others to implement is the best way to go.
So, just ask yourself, "What nouns do I want to give CRUD to, and am I going to exhaust people who wish to consume my API?"