Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hierarchical RESTful URL design

I have perused the questions asked about this, but I still don't have a definitive answer.

I have an application and would like to build a RESTful API to expose a subset of information. I have three resources:

  1. users
  2. reports
  3. photos

Users have reports and reports have photos. Photos cannot exist outside of reports and reports cannot exist outside of users.

I have designed the following URLs for my requirements

User login, server responds with token which is sent in the header of all API calls

GET example.com/api/ 

Get user info

GET example.com/api/users/{username} 

Get all user reports

GET example.com/api/users/{username}/reports 

Get all photos of a report

GET example.com/api/users/{username}/reports/{report_id}/photos 

Add a photo

POST example.com/api/users/{username}/reports/{report_id}/photos 

Delete a photo

DELETE example.com/api/users/{username}/reports/{report_id}/photos/{photo_id} 

Modify photo description

PUT example.com/api/users/{username}/reports/{report_id}/photos/{photo_id} 

Questions

  1. Is it good practice to add a resource id in the URL, i.e. resource/id, or should this rather be added as a query parameter?
  2. Is this method of chaining resources, i.e. resource/id/sub-resource/id/etc., acceptable and good or should I put all my resources at the top level and specify its position with query parameters?
like image 898
Mauritz Hansen Avatar asked Oct 20 '11 09:10

Mauritz Hansen


People also ask

What is a RESTful URL pattern?

Under REST principles, a URL identifies a resource. The following URL design patterns are considered REST best practices: URLs should include nouns, not verbs. Use plural nouns only for consistency (no singular nouns).


2 Answers

Nothing wrong in this design.But this creates long URL which sometime are difficult to understand and the user of the API needs to know the hierarchy.Moreover the consumer of the API need to write more code in little bit non-standard way(Even though it can be done, but will be little messy). Think this from a different perspective You have three resources and each has its own identity.So if we refactor the above URI's it will looks like below (I am demonstrating only GET)

User Resource:

Get users list

  GET example.com/api/users 

Get specific user

  GET example.com/api/users/{username} 

Report Resource:

Get all reports

 GET example.com/api/reports 

Get a specific report

 GET example.com/api/reports/{report_id} 

Photo Resources

All Photos

GET example.com/api/photos 

Specific Photo

GET example.com/api/photos/{photo_id} 

User All Reports

GET example.com/api/reports?username={userName} 

Specific report of a user

GET example.com/api/report?username={userName}&report_id={reportId} 

User All Photos

GET example.com/api/photos?username={userName} 

User All Photos for a report id (You may not need user Name if report_id is unique irrespective of the user, which will further simplify the URI)

GET example.com/api/photos?username={userName}&report_id={reportId} 

All photos of a report

GET example.com/api/photos?report_id={reportId} 

This simplifies the understanding and more standard code can be written on the consumer side using this approach.

like image 148
cometpg Avatar answered Oct 10 '22 21:10

cometpg


IMHO you are modelling it well.

Regarding 1 I'd rather go with resource/id rather than query param. But one thing you must have in mind when modelling is the cache mechanism by proxy and so on. So do not forget the headers.

I go for query params for filtering and those sorts.

About the login, the credentials should be in the headers, and no specific resource is needed. Just apply per resource security.

like image 44
ssedano Avatar answered Oct 10 '22 20:10

ssedano