6

we are currently designing an internal REST api. we have the following use case:

  1. a user (109) wants to read a message that he has sent to another user (110)
  2. the reading user (109) is known to the app through his token credentials that he received after authenticating (while doing the GET request)
  3. we assume in this example the user 109 was the sender and 110 the receiver

to summarize from the users perspective "give me the mail that i (109) have sent to 110"

the following URIs came to our mind but we can't decide which one to take:

a) GET http://localhost:9099/api/mails/109?receiverUserId=110
b) GET http://localhost:9099/api/mails?senderUserId=109&receiverUserId=110
c) GET http://localhost:9099/api/mails?receiverUserId=110
d) GET http://localhost:9099/api/mails/me/to/110 (when logged in as 109 via token credentials we know that "me" is 109)
f) GET http://localhost:9099/api/mails/109/to/110 (explicit request, e.g. for admins … has to be guarded against illegal access)

all the links are "context sensitive" that is sending one of the links to the receiver (110) will yield different results executing the GET request.

i would like to know your opinion on what url to use.

any help highly appreciated.

cheers marcel

Marcel
  • 710
  • 8
  • 23

3 Answers3

2

Different responses to different clients, for same URL is okay.

StackExchange does it:

GET /me/comments/{toid}

which is documented here.

Twitter does it too:

GET /statuses/home_timeline

which is documented here.

Both of those URLs infer the logged in user based on authentication. Yes, it defeats caching if users share a cache, but IMO, this is okay. Whether or not this breaks the 'resource identification' constraint of REST is probably debatable. The answer to this question, and a subsequent comment there shows to me why it is debatable.

In fact, among the options, you do mention URLs which are not 'context sensitive':

GET /api/mails?senderUserId=109&receiverUserId=110

This one will always return messages from 109 to 110. But while one client would want to see this result when viewing 'sent' messages, the other would want to see this result when viewing 'received' messages. Kind of weird eh? Plus, on the server you'll have to check that the authenticated user is 109|110, else throw a 401 UNAUTHORIZED.

I would go with something like:

GET /mail/sent

returns all sent mail. And:

GET /mail/sent?to=110 (like applying a 'filter' to /mail/sent)
OR
GET /mail/sent/110 (clean URL)

returns mail sent to 110.

Community
  • 1
  • 1
ArjunShankar
  • 23,020
  • 5
  • 61
  • 83
1

"Context sensitive" links are bad idea for a REST API (in particular, this hinders caching). If you want to just use HTTP this is OK.

So I would suggest using URLs that do not depend on current user and limit access to them according to your rules.

Petr Gladkikh
  • 1,906
  • 2
  • 18
  • 31
0

In my opinion, you need 2 layers:

One is the internal layer, which doesn't require user authentication, it's only accessible from internal components. It includes APIs like

GET http://localhost:9099/api/mails?senderUserId=109&receiverUserId=110

The advantage of this layer is the testability, reusability and cachability.

The other layer is the external layer, which requires user authentication and is accessible from external clients. It includes APIs like

GET http://localhost:9099/api/mails?receiverUserId=110.

Clients must login to get the token credentials, then server can get the user info from this token, and map the external API call to internal API call.

You may have different kinds of authentication methods, but the internal layer will not be changed, you just need to map different external layers to the internal layer.

Dagang
  • 24,586
  • 26
  • 88
  • 133