Is an API endpoint that differentiates what resour

2019-04-18 16:02发布

Important note

The focus of this question is on API endpoints that differentiate which resources are returned depending who authenticates, e.g. Alice gets resource A and B returned, and Bob gets resource X and Y.

It is NOT about differentiating the representation of resources returned.

All the endpoints return JSON representations of resources.

Preface

Please consider the following three potential API endpoint designs, all returning thing resources of a user.

Endpoint A

GET /things

If authentication credentials for <user_x> are provided with the request, it returns thing resources that specifically relate to <user_x>. For example, authenticating user Alice gets resource A and B returned, and authenticating user Bob gets resource X and Y.

So the differentiation of the response for different authenticating users is on which resource instances are returned and NOT on what information of these instances is returned (i.e. the resource representation).

When authentication fails a 401 response is returned.

Endpoint B

GET /user/<user_x>/things

Endpoint C

GET /things/?user_id=<user_x>

Both endpoint B and C provide the thing resource instances related to <user_x>, iff the authenticating user has the right to access these thing resources.

The representation of the thing resource instances returned, e.g. what information about the resources is returned, can vary depending which user authenticates. For instance, <user_x> or an admin user might get back richer data per resource instance then a user with limited access rights.

Authenticating users that don't have any access rights to thing resources of <user_x> will get a 401 response.

My questions

I would like to have answers to the following questions:

1) Is Endpoint A RESTful?

2) Does Endpoint A have a good URI design?

3) Are Endpoints B and C RESTful?

4) Do Endpoints B and C have a good URI design?

I'm looking forward to your answers. I also provided my own answers below and would be grateful for feedback on that as well.

Thank you!

— Freddy Snijder

4条回答
贼婆χ
2楼-- · 2019-04-18 16:52

This is a very good question and the exact question I had been asking myself while currently developing an API for a project I am working on. I am relatively new to REST so are going through a steep learning curve and are therefore far from being an expert!

I have been reading the "RESTful Web Services Cookbook" by Subbu Allalaraju.

For what it is worth these are my thoughts, they are very similar to the answer you have provided yourself. In practice, I am sure that it is a common scenario that the authentication credentials impact on the information returned for the same URI. The credentials are effectively just another query parameter.

1) Is Endpoint A RESTful?

Yes, it is stateless as the authentication credentials are passed from the client with the request.

It is idempotent as per https://www.w3.org/Protocols/HTTP/1.0/spec.html section 10.2 Authorization "Responses to requests containing an Authorization field are not cachable." so the same credentials will always retrieve the same result (the authenticating user's list of things).

2) Does Endpoint A have a good URI design?

No, it is effectively the same as Endpoint B or C where the user makes a request to retrieve their own things, but with less flexibility and clarity.

3) Are Endpoints B and C RESTful?

Yes, they are stateless and idempotent.

4) Do Endpoints B and C have a good URI design?

Yes, I think either may be a valid design. There are endless discussions on the pros and cons of each approach!

I have chosen to go with something similar in my own API.

GET /user/01/things (authenticating correctly as user 01)

Response 200 OK: Yes user 01 of course you can see your own things.

GET /user/01/things (authenticating correctly as user 02)

Response 200 OK: Yes user 02 you are a superuser and can see what things user 01 has (or perhaps a subset of them).

GET /user/01/things (authenticating correctly as user 03)

Response 403 Forbidden: No user 03 even though you have authenticated correctly you are just a general user and cannot see what things user 01 has. Or you could return Response 200 OK and include similar information in the response data, it all comes down to how you design your API and how much information you need to be able to pass back in this situation, I think either approach is valid.

GET /user/01/things (authenticating incorrectly as user 01)

Response 401 Unauthorized:

List of HTTP status codes

查看更多
爷的心禁止访问
3楼-- · 2019-04-18 17:01

I modified my old answer. I assume we are talking about web documents, so the /things/1 identifies a web document and not a real word thing. (Read more about this here: http://en.wikipedia.org/wiki/Dereferenceable_Uniform_Resource_Identifier and here: https://tools.ietf.org/html/rfc6920 .)

1) Is Endpoint A RESTful?

2) Does Endpoint A have a good URI design?

3) Are Endpoints B and C RESTful?

4) Do Endpoints B and C have a good URI design?

The answer to questions 1 and 3 is yes, you can send different representations of the same resource to users with different permissions. (If you want to cache these responses you should do that by using the vary header.)

The answer to questions 2 and 4 is that depends on how you define "good URI design". Your URIs are perfectly valid and since REST does not have any URI structure constraint and there are no standards about how to design REST URIs for different applications (except ofc. the URI standard and URI template standard), I would say they are good.

There is a similar question here: RESTful URL design: public vs private API, hierhachy API design pattern, URI vs URL design? about this hierarchical vs. flat URI problem if you want to read a more elaborate opinion of mine about this.

查看更多
Explosion°爆炸
4楼-- · 2019-04-18 17:02

Well, first of all, in HTTP the representation of a resource is handled by the header Content-Type and Accept.

But the clients can only suggest the format they prefer. The server is in charge of serve the representation that he wants.

Talking about security, it's perfectly right for me to return a representation based on the security level of the token.

Talking about your URL, I always prefer URL parameters instead of query parameters (some engines doesn't cache GET request with query parameters).

But it depends on the structure of your data. If user_id is inside things, it should be represented in the URL: /things/user_id/xxxxx.

On the other hand, if user_id is not related to the resource things, consider remove this parameter and add it as a header (be careful with GET request and cache times).

查看更多
够拽才男人
5楼-- · 2019-04-18 17:07

UPDATED 18 March 2015 13:05 CET to include feedback in the comments of the question and answers given.

RESTfulness

From a purist point of view non of the endpoints are RESTful. For instance, the question doesn't state if the responses contain links to the resources such that the client can retrieve the resources without needing knowledge about how the URIs to the resources are constructed. In fact, as pointed out in this blogpost, almost no API defined in practice, other then the World Wide Web itself, can be considered RESTful.

So is there nothing useful to say about these endpoints? I think there is. We can talk about statelessness and idem-potency of processing the endpoints, which is important to scalability. And we can talk about safety of endpoints which is important to security.

For all endpoints you could state the following:

Is it stateless?

Yes, user authentication credentials are a part of the application state and are send with every request, thus everything the server needs to know to handle the request, without keeping state, is in the request. (The complete state is transferred)

Since these endpoints process GET requests, are they idem potent?

Endpoint A) : Yes, because the request to endpoint A, including the user authentication credentials, should be considered as a whole: no matter how often you repeat the same request, with the same credentials, you will always get the thing resources for the authenticating user.

However, If you only consider the URI, the request is actually not idem potent, because the response changes depending on the credentials provided.

Endpoint B) and C) : Similar to A), you will always get the thing resources of <user_x> provided in the URI, no matter how often your repeat it.

On top of that the requests are also idem potent only considering the URI itself, everything you need to know about the request is in the URI, the user credentials can only change the representation of the returned thing resources, not which resources are returned.

Since these endpoints process GET requests, are they safe?

Yes, because the request does not alter any data and does not have any other side effect.

URI design

Although from a purist REST perspective URI design is considered irrelevant, in a practical situation where software developers and API end-users use and deal with the URI design is relevant.

Does Endpoint A have a good URI design?

Yes and No. When this URI is hidden from an application user, and this will not be bookmarked or shared this design is fine. However, when this URI is exposed to end-users this URI is not designed well because when sharing this as a link the recipient won't see the same data unless she authenticates as the same user.

Do Endpoints B and C have a good URI design?

Yes, the end-user can understand semantically what the endpoint is about and the URIs are sharable between users.

So, instead of defining all three end points you could chose to only define endpoints B and C because they can provide everything what endpoint A could provide, plus it is obvious from the URL what is requested.

Please let me know what you think. Thank you!

— Freddy Snijder

查看更多
登录 后发表回答