1

I want to provide a me endpoint because not everyone should have access to all resources. The current logged in user should only have access to his own resources. So let's assume you would have a simple Todo REST API with an endpoint returning all tasks from a single user

GET /users/{username}/tasks

The current logged in user should not be able to get information about other users. A possible solution for this would be

GET /users/me/tasks

This has already been discussed here

Designing URI for current logged in user in REST applications

The problem is that I also want to keep the endpoint from above for development purposes (a private/hidden endpoint). Unfortunately both endpoints match the same route. So me could be the username.

I don't want to prevent a username called me with an if-statement like

if(username == "me")
    throw new ConflictException("Username 'me' is forbidden");

I think this would be bad design. A possible solution would be to avoid embedding me in a resource and instead embed the resources in me endpoints. So instead of

GET /users/me/tasks
GET /users/me/orders
POST /users/me/tasks
PATCH /users/me/username
DELETE /users/me/tasks/{taskName}

I could remove the users resource and make me the initial base resource. As you might guess /users/:username extracts the username from the url parameter and /me extracts the username from the json web token but both endpoints run the same logic.

So when I want to keep private/hidden endpoints to fetch a user by username do I have to make me a separate resource? Or is there a way to keep me only as a replacement for the username parameter?


EDIT

I tried to create a simple route example. As you can see most of the endpoints of users and me are mirrored and only differ by the user identification (username as parameter or jwt payload). And for this sample only the me endpoints are accessible to everyone. Other endpoints are private / hidden.

users

GET / => get users => private
GET /:username => get user => private
GET /:username/tasks => get tasks from user => private
GET /:username/tasks/:taskName => get task from user => private
POST /:username/tasks => create user task => private
PATCH /:username/username => update username => private
DELETE /:username => delete user => private
DELETE /:username/tasks/:taskName => delete user task => private

tasks

GET / => get tasks => private

me

GET / => get current logged in user => public
GET /tasks => get tasks from current logged in user => public
GET /tasks/:taskName => get task from current logged in user => public
POST /tasks => create task for current logged in user => public
PATCH /username => update username => public
DELETE / => delete current logged in user => public
DELETE /tasks/:taskName => delete task from current logged in user => public

1 Answers1

2

I think you are getting confused because your definitions are a bit tangled.

Here's the good news: REST doesn't care about the spelling conventions you use for your identifiers. So if it makes your life easy to have

GET /users/12345/tasks
GET /me/tasks

Then you can implement both of those, make sure that the access restrictions are correct, and off you go.

There's nothing wrong, from a REST perspective, about using

GET /users/12345/tasks
GET /users/me/tasks

The spellings of the target-uri are different, which means that from the perspective of a general-purpose client they identify different resources.

BUT... the routing implementation that you are using to implement your API may not allow you to easily distinguish these two cases. What you have effectively got here are two different matches for the same pattern, which requires some extra clever to remove the ambiguity; if your routing library/framework doesn't offer that, then you are going to have to shim it in yourself.

And, as you note, you've got a huge mess if the token "me" itself could match a real identifier.

REST doesn't have a concept of "base resource" - at least, not one that lines up with what you are thinking about. There's no inherent relationship between /users and /users/12345 from the REST perspective. Many server frameworks do treat request handling as a hierarchy of "resources", but again: that's an implementation detail of your particular server.

REST really only cares about your interface - that you understand HTTP requests in the standard way.

Which all brings us back to the good news; since REST doesn't care what spelling conventions you use, you are welcome to make any arbitrary choices you like... including whatever spelling convention makes your internal routing framework easy to work with.

So if your routing framework is telling you to create a different "initial base resource" to support your family of "me" endpoints, then just do that.

VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
  • hey, thanks for your reply. I added a small example to my question, what do you think about it? –  Jun 18 '20 at 06:26