Two resources:
/user
/product
The database table name is user_product and it describes relation between user and product. However, endpoint POST /user/{id}/product/{id} would indicate updating a specific product under user, as opposed to creating a new relation.
I have therefore named the resource POST /user/{id}/product/{id}/purchase, which defines fictional resource purchase. After all, this is what the data in the table represents.
I am aware that the original dissertation describing REST principles does little to standardise naming. I'd like to know what are industry established conventions for naming resource that identifies a relationship between two resources?
I would guess that your purchase is stored in a database somewhere and the actual purchase assigned its own ID. Why not use that ID directly as in /purchases/{purchase-id}?
Your example /user/{id}/product/{id}/purchase won't work if one user has more than one purchase of the same product. Unless of course the resource either signals "The user has at least one purchase of product X" or returns a list of all purchases of product X for that user - which looks more like a query (which is fine to assign its own resource).
I have therefore named the resource POST /user/{id}/product/{id}/purchase.
Please be aware that you don't include method names (like POST) in resource names. And why the POST? Is it for creating/modifying the relation - or did you mean GET to get some information about the relation?
I am aware that the original dissertation describing REST principles does little to standardise naming. I'd like to know what are industry established conventions for naming resource that identifies a relationship between two resources?
No, but if you want some hints then I wrote a piece on this subject here: http://soabits.blogspot.dk/2013/10/url-structures-and-hyper-media-for-web.html
Related
A person can have many reviews. My endpoint to CREATE a new review is:
post /person/{id}/reviews
How about the endpoint to UPDATE a review? I see two options:
Stick to the parent resource: patch /person/{person_id}/reviews/{id}
Only have reviews in the URI: patch /reviews/{id}
I could be sold on using either of them:
It's consistent with the previously defined endpoint, but {person_id} is not needed.
It's 'efficient' as we're not specifying a parameter ({person_id}) that is not really needed. However, it breaks the API convention.
Which one is preferable and why?
The client shouldn't have to know about ids at all. After a client creates the review, the response should include the URI to the new review like this:
HTTP/1.1 201 Created
Location: /person/4/reviews/5
The client now has the full URL to the review, making it completely irrelevant how it looks like and what information is here.
Don't forget that the URL itself is a system to create globally unique IDs, that embed not just it's own unique identity but also information on how to access the data. If you introduce a separate 'id' and 'person_id' field you are not taking advantage of how the web is supposed to work.
In terms of API design, without knowing too much detail about OP's situation I'd walk along these guideposts:
Only have reviews in the URI: patch /reviews/{id}
It's 'efficient' as we're not specifying a parameter ({person_id})
that is not really needed. However, it breaks the API convention
The "efficiency" allows for a more flexible design. There's no existing API convention broken at this point. Moreover, this approach gives you the flexibility to avoid the need of always needing the parent resource ID whenever you display your items.
Stick to the parent resource: patch /person/{person_id}/reviews/{id}
It's consistent with the previously defined endpoint, but {person_id}
is not needed.
The consistency aspect here can be neglected. It's not beneficial to design endpoints similarly to other endpoints just because the previous ones were designed in a certain way.
The key when deciding one way or the other is the intent you communicate and the following restrictions that are put on the endpoint.
The crucial question here is:
Can the reviews ever exist on their own or will they always have a parent person?
If you don't know for sure, go for the more flexible design: PATCH /reviews/{id}
If you do know for sure that it always will be bound to a particular person and never can have a null value for person_id in the database, then you could embed it right into your endpoint design with: PATCH /person/{person_id}/reviews/{id}
By the way, the same is true for other endpoints, like the creation endpoint POST /person/{person_id}/reviews/{id}. Having an endpoint like this removes the flexibility of creating reviews without a person, which may be desirable or not.
I am designing a REST service for my company. No one here has had much experience with REST so I read through a few books on the subject but I am stuck on resource design of a POST vs. the resource design of a GET request for the same data. Particularly in the case of foreign relationships.
For instance I have a class PurchaseRequest which represents a request to purchase some fixed asset. Behind the scenes my service is an interface to a relational DB. There is a PURCHASE_REQUEST table which has a foreign key to an ASSET table (Defining which of a fixed list of assets are being requested) and a PERSON table (Defining which of the users is doing the requesting). Currently in my service when a GET command is issued for a purchase request, the service returns the whole thing: An XML representation of the PURCHASE_REQUEST table entry along with a list of asset entries like so:
<PurchaseRequest>
<ID></ID>
<RequestDate></RequestDate>
<Requestor href="/requestors/requestorID">
<RequestorID></RequestorID>
<FirstName></FirstName>
<LastName></LastName>
</Requestor>
<RequestedAssets>
<RequestedAsset href="/assets/AssetNumber" >
<AssetNumber></AssetNumber>
<Year></Year>
<Make></Make>
<Model></Model>
<Cost></Cost>
</RequestedAsset>
<RequestedAsset href="/assets/AssetNumber" >
<AssetNumber></AssetNumber>
<Year></Year>
<Make></Make>
<Model></Model>
<Cost></Cost>
</RequestedAsset>
<RequestedAsset href="/assets/AssetNumber" >
<AssetNumber></AssetNumber>
<Year></Year>
<Make></Make>
<Model></Model>
<Cost></Cost>
</RequestedAsset>
</RequestedAssets>
</PurchaseRequest>
This works pretty efficiently. The consuming application makes a single request and gets the whole thing and links to the full resource requestor resource or asset resource if they need them.
The problem comes on a POST. My gut tells me to try to use the same resource layout for POSTing a new purchase request as I used to retrieve an existing one. This is what all the examples in the books I have read do anyway. I don’t need to know anything more than the Asset Number and Requestor ID to fulfill the POST. That means that data is not necessary but the inefficiency alone is not what bothers me. The main thing is you should not be able to edit the year, make or model of an asset when creating a purchase request, those fields are pre-defined. You also should be able to create a new asset definition when creating a purchase request. Similarly you should not be able to update/create a person's details when creating a purchase request. There are separate services for creating/updating people and assets.
The only thing I can think of is to define a different DataContract class for the POST which has the minimum info to identify an asset or a person and does not expose those fields which cannot be updated. I really don’t love this option because it is going to create a large number of DataContracts classes (nearly all of the tables in my DB have foreign relationships, this is not isolated to one request or I would not be worrying about it) However I really don’t love my current design because REST does not have read-only fields.The burden is now on the consumers of my service to constantly be checking, "does it save this field… what about this one?..." Has anyone else ran into this issue? Is it common to have to define a separate DataContract class for POSTing and GETing? Seems like a pretty basic design question but I don’t see a lot of posts out there on the subject so I am hoping I just missed something. Any help is appreciated.
I'm developing a rest API for our business system. We have the following resources so far:
/sales/orders
/sales/orders/{orderno}
/sales/order-items
There will be lots of resources when the API is finished, so we need to structure it in a good way to make it easy to understand. My question is: should /sales/order-items instead be /sales/orders/order-items? There is maybe no correct answer here, but what would you prefer?
One more question: The sales/order-items resource will list either all open items or all shipped items. It will not be possible to get all order-items regardless of status (open/shipped). The resource URI could the be like this sales/order-items?orderstatus={OPEN/SHIPPED} (the orderstatus query parameter would be mandatory then) or it could be two resources like this sales/order-items/open and sales/order-items/shipped. What is the preferred?
A resource is 'any information that can be named'. Your URIs should be entity based. 'order-items' is not an entity, but a data type.
/sales/order/order-1456321 is the Entity you most likely want. Which would contain the data of all order items.
If you wish to restrict access, you can return a client error if no query string is supplied. and having
/sales/order/order-12345?status=open
etc. Hope this helps.
EDIT:
/sales/order-items or /sales/orders/order-items?
This is domain specific, and really should be answered by a domain expert. Your URI Hierarchy provides scope (and so detail) to your resource. So as an educated guess, It does not make sense to have "order-items" within the scope of "/sales/orders/" because "order-items" is not an "order".
/sales/ordered-items
seems the most sensible answer.
On a personal note, and not to question your domain too much, Having a strong understanding of the flow of the business and information that's stored may result in something along the lines of these suggestions;
/sales/orders?status=open - Are all orders shipped at once?
/sales/orders/order-1234/packages?status=open - Are orders split into packages?
We are building a webapplication which uses a database. Also we use an object relational mapper to access the database. One aspect of authorization in the webapplication is that the user may access an object referred to by an URL. The URL contains a unique id (for example the Primary Key) to a specific record in the database. Consider the following example.
a user may belong to many groups and a group may have many users (many-to-many).
a survey belongs to a group (many-to-one).
a survey may have multiple questions. (many-to-one).
Say we have the following URL: http://app.local/question/edit/10. This means we want to edit question with PK 10. Now, we want to verify if the logged in user may access question with PK 10. This can be done by retrieving this question, then it's survey then it's group and then all its users. If any of the users is the same as the logged in user the logged in user may access the question.
To generalize this a bit; we want to check if a record is reachable from another record by the known many-to-one or many-to-many relations. So if there is a many-to-one relation (like with a survey and a question then we should check if a user is reachable from the question through the survey and then through the group. The group has a many-to-many relation with the user so we should check if any (not all) of the users is the same as the logged in user.
If a table has multiple many-to-one relations, say; we can attach a CSS template to a survey and this template also belongs to a group then we have to check if a user is reachable from all many-to-one relations (thus the group and the template). The same holds of course for multiple many-to-many relations.
Are there Object Relation Mappers which support this behaviour? And what is this behaviour called, maybe reachability? Does Propel (for PHP) support this behaviour? I think this reachability can be done in any of the following two ways:
Execute a query to get each "parent", uses many queries)
Join all necessary tables to see if a record exists (the reachable users matches the logged in user) in one query.
Furthermore this behaviour of the ORM should support nested sets, thus if a group contains nested set behaviour it should also try to reach a user through the group's parent.
I don't think this kind of behaviour should be restricted to authorization; objects should simply be able to see if they can reach another object.
Note that I do not mean persistence by reachability: http://jpaobjects.sourceforge.net/m2-site/main/documentation/docbkx/html/user-guide/ch08s03.html.
Or... am I simply looking at this authorization wrong and is there a far better and different approach with an ORM?
I've handled this in the past using nested resources in Ruby on Rails (which uses the Active Record ORM). Rather than http://app.local/question/10/edit, the URI would be http://app.local/survey/5/questions/10/edit
In the controller you load both the question and survey. You check authorization by comparing the survey to the authenticated user's group memberships. One way to engineer this would be to embed this logic into the User class. For example, in the controller you have question and survey (and the relationship between the two is well understood by the ORM, i.e. question.survey). You could then check access as user.hasAccess?(question), which would be a relatively easy method to write. Pseudocode:
class User < ActiveRecord::Base
def hasAccess?(question)
return question.group.users.include?(self)
Yes, this will result in several queries behind the scenes, but ORMs do the work. I do it this way because you're left with solid schema and easy to read code. Don't optimize until you actually have a performance problem.
Currently I am developing an API and within that API I want the signed in users to be able to like/unlike or favorite/unfavorite two resources.
My "Like" model (it's a Ruby on Rails 3 application) is polymorphic and belongs to two different resources:
/api/v1/resource-a/:id/likes
and
/api/v1/resource-a/:resource_a_id/resource-b/:id/likes
The thing is: I am in doubt what way to choose to make my resources as RESTful as possible. I already tried the next two ways to implement like/unlike structure in my URL's:
Case A: (like/unlike being the member of the "resource")
PUT /api/v1/resource/:id/like maps to Api::V1::ResourceController#like
PUT /api/v1/resource/:id/unlike maps to Api::V1::ResourceController#unlike
and case B: ("likes" is a resource on it's own)
POST /api/v1/resource/:id/likes maps to Api::V1::LikesController#create
DELETE /api/v1/resource/:id/likes maps to Api::V1::LikesController#destroy
In both cases I already have a user session, so I don't have to mention the id of the corresponding "like"-record when deleting/"unliking".
I would like to know how you guys have implemented such cases!
Update April 15th, 2011: With "session" I mean HTTP Basic Authentication header being sent with each request and providing encrypted username:password combination.
I think the fact that you're maintaining application state on the server (user session that contains the user id) is one of the problems here. It's making this a lot more difficult than it needs to be and it's breaking a REST's statelessness constraint.
In Case A, you've given URIs to operations, which again is not RESTful. URIs identify resources and state transitions should be performed using a uniform interface that is common to all resources. I think Case B is a lot better in this respect.
So, with these two things in mind, I'd propose something like:
PUT /api/v1/resource/:id/likes/:userid
DELETE /api/v1/resource/:id/likes/:userid
We also have the added benefit that a user can only register one 'Like' (they can repeat that 'Like' as many times as they like, and since the PUT is idempotent it has the same result no matter how many times it's performed). DELETE is also idempotent, so if an 'Unlike' operation is repeated many times for some reason then the system remains in a consistent state. Of course you can implement POST in this way, but if we use PUT and DELETE we can see that the rules associated with these verbs seem to fit our use-case really well.
I can also imagine another useful request:
GET /api/v1/resource/:id/likes/:userid
That would return details of a 'Like', such as the date it was made or the ordinal (i.e. 'This was the 50th like!').
case B is better, and here have a good sample from GitHub API.
Star a repo
PUT /user/starred/:owner/:repo
Unstar a repo
DELETE /user/starred/:owner/:repo
You are in effect defining a "like" resource, a fact that a user resource likes some other resource in your system. So in REST, you'll need to pick a resource name scheme that uniquely identifies this fact. I'd suggest (using songs as the example):
/like/user/{user-id}/song/{song-id}
Then PUT establishes a liking, and DELETE removes it. GET of course finds out if someone likes a particular song. And you could define GET /like/user/{user-id} to see a list of the songs a particular user likes, and GET /like/song/{song-id} to see a list of the users who like a particular song.
If you assume the user name is established by the existing session, as #joelittlejohn points out, and is not part of the like resource name, then you're violating REST's statelessness constraint and you lose some very important advantages. For instance, a user can only get their own likes, not their friends' likes. Also, it breaks HTTP caching, because one user's likes are indistinguishable from another's.