I'm looking for some guidance around REST design for user account endpoints. I generally understand REST and some of the principles involved, with paths being used to fetch items from a resource:
/user/{id}
This is generally fine, but I've run across a design problem that could have two options. In many API's I've seen it can be common to have a user namespace for the account:
/user/self/objects
Which would then return the objects belonging to that user. However, I've also seen this – which I think also makes sense for returning the authenticated user's objects:
/objects/?user=self
Does anyone have some thoughts on these two from a design perspective?
-
Using paths vs query params is completely equivalent as far as HTTP/REST is concerned, but a path-based layout is more common nowadays.amon– amon2023年01月12日 10:25:03 +00:00Commented Jan 12, 2023 at 10:25
3 Answers 3
As @Amon says, both can do the job, however, from the design perspective, I would dare to say there could be subtle differences.
While /self/objects
points to very concrete (unambiguously) resources (mines), /objects?user=self
is pointing to a search which result happens to be the same.
An advantage of the first over the second can be security. The first can't be tampered. Whoever calls /self/objects
won't get ours, will get theirs, unless we are impersonated.
/self/objects
doesn't allow others to guess others' objects. This API disables unwanted searches (attack surface for guess attacks).
While we could achieve the same level of "security" with /objects
, the content won't be so evident for developers (are we getting all objects? only ours?) due to the lack of context.
In a nutshell, unless we want to allow searches, there's no need for /objects?user=self
.
GitHub has an open API with a RESTful design which I've used myself for inspiration to make my own APIs RESTful and generally sensible. It uses neither of your approaches, perhaps you can reconsider a third option?
The current user
GET/PUT/PATCH /user/
is used for fetching/manipulating the currently authorized user (identified by the provided Authorization header token).
GET /user/repos
is used for fetching the the currently authorized user's repositories.
For other users
GET /users/...
is used for fetching all users. Finding a user based on an identifier, listing users, etc.
GET /users/{username}/repos
is for fetching some resource (e.g. repositories) belonging to a specific user.
Presenting query parameters as path elements doesn't mesh well with HTTP error codes. GET /users?username=bob
would conventionally return 422 if the username "bob" does not exist. But GET /users/bob
looks like it should return 404. My practice is that it should still return 422, mainly because 404 is cacheable by default and 422 is not. Parameters masquerading as path elements increase the likelihood of an invalid path element becoming valid later.