Very intentional indeed!
This enables the caching mechanism, and is one of the reasons behind Resgate’s outstanding performance.
If 1000 clients requests a resource (model or collection), Resgate only need to request it once from the service, and then return the same result to all 1000 clients. And it can cache it for future requests.
Now, if the returned resource could depend on a token or CID, there is no way Resgate could determine if those 1000 clients would get the same data if they have different tokens… and Resgate would have to make 1000 get requests instead of 1. Thus making the caching mechanism close to worthless for logged in clients.
Sooo, that said. How to do user-specific resources?
Quite simple. Whatever information that is required to identify the unique resource should be part of the resource ID (including the query part).
Example
Let’s say we have a movie database service.
And the user/client has a token:
{ "userId": 42, "role":"user", "countryId": "SE" }
If we have a resource (collection) which contains a list of the users favorites movies, those resource ID’s could look like this:
"moviedb.myFavoriteMovies" // Bad. This would not be unique for each user, and we cannot rely on the token
"moviedb.user.$userId.favoriteMovies" // Good. The userId it is part of the resource name
Another resource giving the top movies. This can also be filtered by country:
"moviedb.topList" // This means top list for _all_ countries
"moviedb.topList?country=SE" // The additional information is provided in the query, instead of relying on token
If the client doesn’t know the userId of the logged in user, you can have a call method that reads it from the token and returns a resource response to the actual resource:
func main() {
s := res.NewService("moviedb")
s.Handle("", // Put the call method on the service root
res.Call("myFavoriteMovies", func(r res.CallRequest) {
// Parse the userId from the token in the call request
token := struct {
UserID string `json:"userId"`
}
r.ParseToken(&p)
// Return a reference to the unique resource for that user.
// Resgate will fetch this resource and return it in the call response.
r.Resource(fmt.Sprintf("moviedb.user.%s.favoriteMovies", p.UserID))
}),
)
// ... do more ... such as adding a handler for "user.$userId.favoriteMovies"
}
Hope that clarifies it
/Samuel