4

I'm designing an web app with React as front-end, and I'm trying to properly understand REST API practices. Reading resources online, one can get the idea that the REST API is seen kind of like an adapter to the database. However, what with "relative" resources? For example the ones related to the current user or the current time.

I'm designing an app that is about learning, it's "relative" concepts, like "current week of the course" are very important.

Would be considered the best practice to have one end-point with all the relative data, like: /api/me.json (so: user id, his active course, current week of the course etc.) , and everything else absolute, like:

  • /api/user/[id]/course/progress.json
  • /api/user/[id]/course/week/[week_id]/progress.json

Or maybe it's ok to have multiple relative resources for example: /api/me/course/progress.json?

Or maybe even: /api/me/course/current_week/progress.json (double relative resource)?

Are there established practices of how to handle such cases?

Łukasz Zaroda
  • 321
  • 2
  • 8

2 Answers2

3

Reading resources online, one can get the idea that the REST API is seen kind of like an adapter to the database.

That's true, you can get that idea. It's not quite right. The REST API could be an adapter for any number of different implementations. That's part of why the REST architectural style was so effective; clients and servers are able to collaborate without needing awareness of each other's internals.

Short answer: any of your choices are fine.

The first piece to understand is the concept of resource in the REST architectural style.

The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time.

"Current user" and "current week" are perfectly reasonable concepts, so of course they can be resources. "Current week" is just a mapping that evolves relative to a clock, "Current user" is just a mapping to the operator associated with the current request. There are no problems there.

As Ewan notes, REST is stateless -- more precisely, the REST architectural style does not allow you to store client state on the server. The effectively means that the message returned by the server can consider only the server's own state combined with the data provided in the request. Another way of thinking of this: the client's requests are not allowed to use pronouns without including the antecedent.

So assuming that "current user" relates to the client (for instance, the human operator working in the browser), there must be some data in the request that communicates which user we are talking about. That could be information encoded into the resource identifier itself, or it could be included in the metadata of the request (for instance, HTTP has an Authorization header that could carry this data).

Of course, part of the point of "current week" is that it changes; next week is different from last week. Alice and Bob are different "current users". So a certain amount of care needs to be taken with caching; making sure that the server is clearly communicating (via the meta data) who is allowed to read copies of the current representation, and how for how long that representation may be considered valid.

For some caching scenarios, it can be useful to link the response back to a different resource with a "canonical" identifier. /user/alice might be the canonical identifier for /me when Alice's request is being processed; /2017-W48 might be the canonical identifier for /current-week. For various use cases, you might redirect a request to the canonical resource, rather than handling it immediately.

VoiceOfUnreason
  • 32,131
  • 2
  • 42
  • 79
0

One of the key things, arguably THE key thing about REST is 'Stateless'.

This means that you can't just hit /me and have the server know who you are. You have to send that data somehow and the HTTP GET way of doing that is either in the path or the query string.

so

/users?id=myid

or

/users/myid

With the later being the 'cooler'. Similarly with the current date, its best to send the date you want rather than have the server pull the current time from the OS.

eg

/courseProgress?userId=[id]&courseId=[courseId]&date=[utcdatetime]

When you have multiple parameters the url starts to get a bit ugly as it becomes more of a RPC than a Resource.

Ewan
  • 70,664
  • 5
  • 76
  • 161
  • But how client will know his id? He has to receive it from somewhere, and this somewhere has to know who he is. – Łukasz Zaroda Dec 01 '17 at 17:12
  • presumably the client has logged in and identified themselves with a username/password or some such? – Ewan Dec 01 '17 at 17:13
  • Yes. Are you aiming at getting id in the response confirming authentication? – Łukasz Zaroda Dec 01 '17 at 17:18
  • I think that would be the usual way. perhaps a jwt with the userid as a claim? – Ewan Dec 01 '17 at 17:21
  • Wasn't the use of `[id]` already established in the question? I thought this was a question about "relative resources." – Robert Harvey Dec 01 '17 at 17:26
  • @RobertHarvey I think this answer implies that after authentication, client should get his ID and no more relativity from there. So in the case of getting information about his "active course", the order of queries would be: `GET /api/user/[my_id]` (here he would get his active course id), and then `GET /api/course/[course_id]/progress/[user_id]` (to get information about his progress). What I have hard time to wrap my head around, is what if he would like to get information about the progress in the "current week" of the course, that may have arbitrary starting and ending date. – Łukasz Zaroda Dec 01 '17 at 17:48
  • I guess `current_week_id` or something could be accessible in the `GET /api/course/[course_id]`? Am I thinking about it right? – Łukasz Zaroda Dec 01 '17 at 17:49
  • i will update but basically /progress?courseId=&date= – Ewan Dec 01 '17 at 17:50
  • @Luken: Yes, when a user logs in to any system, they are be handed some sort of token that allows the system to identify the user on subsequent requests. It's not generally a separate GET; the user already has been given the token in the response to his login request. – Robert Harvey Dec 01 '17 at 17:56
  • Statelessness of REST does not mean that only absolute URL can be used. `/api/me` can return the resource representing the current user based on the credentials that are also included in the request. – Bart van Ingen Schenau Dec 02 '17 at 07:26
  • correct, but you'll notice I phrase it quite carefully. – Ewan Dec 02 '17 at 08:26