Reputation: 8401
Let's say I have this URI endpoint:
:GET /v1/permissions
Which select all of the permissions on version 1.
One also can request this:
:GET /permissions
Which will request all permissions by the latest default version.
Now I want to select all of the permissions from a specific user.
I want to know what is the proper and respectable way to send the identifier of the user - in the URI endpoint OR in the http request headers OR as a GET param.
For example:
Method 1:
:GET /v1/groups/:id/permissions
Method 1.1:
:GET /v1/:id/permissions
Method 2:
:GET /v1/permissions,
"If-Match": "[REPLACE_ID_HERE]" (header)
Method 3:
:GET /v1/permissions/?groups=REPLACE_ID_HERE
All of them will work.
But which is the proper way?
Upvotes: 3
Views: 15258
Reputation: 334
The most common way of designing a REST API is following the resources (and - or sub-resources) structure. i.e. api url will start with your resource name followed by a unique ID for the resource in case of Single resource GET, PUT(update) or DELETE.
Ex : 1. /users/$unique_user_id - HTTP GET - Fetches the single user detail.
/users/$unique_user_id - HTTP PUT - updates the user details identified by the id with the related data.
/users/$unique_user_id - HTTP DELETE - Deletes the user identified by the ID.
If your case handles a well established relation between 2 resources you can handle them as sub-resources of the parent. Ex : /users/$user_id/permissions /groups/$group_id/permissions
This model will suit if you won’t get a requirement to fetch permissions for multiple resources(kind of filtering) Ex : /permissions?group_ids=1,2,3 /permissions?user_ids=4,5,6
Upvotes: 0
Reputation: 11870
Two points upfront:
One of those standards is that REST Urls are specific to resources and ids embedded in those Urls reference resources of the same type. Thus GET /groups/:groupdId
is orthodox (a standard implementation that matches the expectations of most programmers) whereas GET /groups/:permissionId
is not.
Coming back to the 4 alternatives you contemplate:
Method 1:
:GET /v1/groups/:id/permissions
Is orthodox, since the resource managed by the endpoint is of type Group
and :id is a Group id.
Method 1.1:
:GET /v1/:id/permissions
Is unorthodox since there is no indication of what resource type the Url refers to.
Method 2:
:GET /v1/permissions,
"If-Match": "[REPLACE_ID_HERE]" (header)
Is unorthodox, since resource ids are expected to be passed as part of the Url.
Method 3:
:GET /v1/permissions/?groups=REPLACE_ID_HERE
Is orthodox, since here the resource is Permission
and the groupId
is applied as a filter, for which request parameters are the adequate means.
Upvotes: 2
Reputation: 130907
But which is the proper way?
It's a common misconception.
The REST architectural style doesn't enforce any URI design (see notes below). It's totally up to you to pick the URIs that better identify your resources.
The URI syntax is defined in the RFC 3986. As general rule, the path is organized in hierarchical form (with segments separated by /
) and can contain non-hierarchical data in the query component (starting with ?
).
These approaches seem to be fine to identify the permissions of a particular group:
/v1/groups/:id/permissions
/v1/permissions?groups=id
The "right" approach would depend on your needs and how you model your API. In the first approach, the hierarchy expresses that the permissions belong to a particular group (the permissions depend on a group to exist). The second approach is more like filtering a collection of permissions by group.
Note 1: The REST architectural style is described in the chapter 5 of Roy T. Fielding's dissertation and it defines a set of constraints that must be followed by the applications that follow such architecture. However it says nothing about what the URIs must be like.
Note 2: The examples of a popular article written by Martin Fowler explaining a model defined by Leonard Richardson suggest a URI structure that looks friendly and easy to read.
Upvotes: 3
Reputation: 2068
As per REST spec, you first need to determine what is the base resource you are requesting for. The name of the resource comes first in the URI. In your case, it's the Permission. Hence the URI will begin with permission, with an optional version prefix (as the whole API is versioned)
Following the resource name, you need to mention either a specific resource or a query parameters to get a broad list. Now here you have two options, based on what you are retrieving. 1) permission for a person: In this case, you need to put query param as the api itself won't be able to guess what is the id for. Hence it will be permissions/?personId=123 2) permission detail of a particular permission: Used when you have a list of permissions pre fetched, maybe as result of above api. In this case the identifier will belong to the resource itself, hence it will be specified as the resource identifier as permissions/5e55 where 5e55 is the primary key of the specified permission of whom detail is being sought after.
The major complexity in such design is properly identify the resource primary identifier and secondary identifier... The primary identifier is put directly in type 2 and secondary is specified as query param.
All said, technically nothing will stop the either request style from working as long as you provide the parsing logic of the URI. REST just says that URI should be able to identify resource properly and does not impose an implementation requirement.
Upvotes: -2