I'm designing a hypermedia API, yes, a RESTful API, with the hypertext constraint.
Each user of the system will access the system using their own credentials, so every request we process is authenticated and authorized. Each user will typically have specific credentials so that they may have different permissione (e.g. none, read, read/write) on each collection.
We want the client to be primed with the one URI that it starts with, which would be perhaps an atom services document, or a hierarchy (draft atom hierarchy extensions) of atom collections.
My question is basically should users see different representations for the same URI, or should users be directed to different URIs based on their permissions?
For example: User A and User B have different permissions in the system. The开发者_JS百科y log in with different credentials, to the same start URI. A successful response may be one of the following 2:
- 200 OK, and User A sees something different than user B on the same URI
- 302 (or other redirect) each user to e.g. /endpoint/userA (which they own)
The tradeoff between cacheability is of course minimal, since resources are cached only by the client and not by intermediaries, but there's a tradeoff for visibility too (URI contains (aythenticated) user ID). Finally there's the future possibility of allowing User A (or a super user) to see what User B sees.
I'm not asking what Twitter or Facebook do, I'm more interested in what REST practicioners have to say about this.
My question is basically should users see different representations for the same URI, or should users be directed to different URIs based on their permissions?
For example: User A and User B have different permissions in the system. They log in with different credentials, to the same start URI. A successful response may be one of the following 2:
- 200 OK, and User A sees something different than user B on the same URI
- 302 (or other redirect) each user to e.g. /endpoint/userA (which they own)
Both ways are RESTful. The representation of a resource can depend on the permissions. The communication is stateless because you send the credentials (username, password) with http auth by every request. Redirection to another representation variant after permission check is a great idea. That way you can completely separate the authorization logic from the resource representation logic, so you can move it even to another server and you can create very well cacheable resource representations. For example by GET /endpoint/userA
you can redirect userA
to /endpoint/userA?owner=true
, because she is the owner of the profile, or you can create a composition of features: /endpoint/userA?feature1=true&feature2=false
etc... It is very easy to setup fine grained access control for that. Another way to stay cacheable if you append the user id to every request's queryString, but this solution with redirection is much cleaner. Thank you for that!
Personally I find this a really tough call to make and I think it depends a lot how much content would change. If the difference is the omission of a few extra details then I would probably treat it as a single resource that varies based on the user.
However, once the differences start to get more significant then I would look at creating different resources. I would still try and avoid creating resources that are specific to a particular user. Maybe for a particular resource you could create a set of subresources, with differing levels of content. e.g.
/Customer/123?accesslevel=low
/Customer/123?accesslevel=medium
/Customer/123?accesslevel=high
This method in combination with the 302 may be sufficient in some cases. For more complex cases you could use multiple query string parameters.
/Employee/123?SocialSecurityNo=yes&SalaryInfo=yes
I do not believe there is an easy answer to this question. I think the answer is similar to most tricky REST scenarios: your solution can be as creative as you want as long as you don't violate the constraints :-)
Option 1, replying with 200 is an acceptable REST response and is more user friendly than option 2.
The Google Data APIs provide a decent REST implementation on top of their user services, and they implement option 1. For example the Google Calendar Data API allows a user to query the person's own feed by performing a HTTP GET request on http://www.google.com/calendar/feeds/default/private/full.
精彩评论