20

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

Community
  • 1
  • 1
Visionscaper
  • 3,979
  • 1
  • 23
  • 26
  • Your questions indicate to me that you don't understand what RESTful means. REST is an overall architectural style (i.e., approach) that is based mostly on principles and patterns. Therefore it doesn't make sense to ask if particular endpoints are RESTful. – Jonathan W Mar 16 '15 at 14:03
  • Also, believe it or not, how you design and organize URIs is not related to REST. The "big deal" for REST is the requirement that links to be passed in the response, giving possibilities for the client for further navigation of resources. While having an intentional design to your URIs can be beneficial, they should be treated as completely opaque by clients. Clients, in turn, should only navigate links based on the relations received and not some pre-conceived notion of how to construct URIs. – Jonathan W Mar 16 '15 at 14:07
  • Jonathan W, I'm sorry but I don't think that you are making a fair assessment. I do understand REST. When I describe the end points I also describe how they behave (how the service behaves to process the requests to these endpoints and how it responds). So when I ask if endpoint X is RESTful I ask if the described behaviour conforms to REST principles and patterns. Behaviour such as idempotency and safety are also important concepts related to REST; I focussed my own answer on these concepts. It is true that I did't mention anything about links passed in the responses. – Visionscaper Mar 16 '15 at 15:31
  • Jonathan W, concerning your remark about URIs : this is why I had two types of questions : one related to the RESTfulness of the endpoint behaviour, the other about URI design, which is indeed a separate subject. – Visionscaper Mar 16 '15 at 15:32
  • Jonathan W, the focus of my question is really about the merits of making a response (here I mean what set of resources are returned) conditional on who authenticates. This is exemplified through Endpoint A. Although, if you think about it, purely from a REST perspective, it doesn't seem to matter. But practically I think it is better to only work with Endpoints such as B and C, because they make explicit, through the URI, what the user of the API needs. I was hoping to get feedback about that. Although the comments you and others make, are really valuable for any one interested in REST. – Visionscaper Mar 16 '15 at 16:24
  • A, B, and C could all be RESTful, or they could all *not* be RESTful. A lot of it depends on what kind of semantics are behind your resource model and what kinds of caching guarantees you want to make. – Jonathan W Mar 17 '15 at 20:24
  • Can you elaborate on that? – Visionscaper Mar 17 '15 at 22:05
  • Endpoint A is more limited in functionality because it presumes that the authorized user making the request wants to see his or her things. Assuming that this is an either/or scenario (i.e, you don't provide for both A and B/C), you would never be able to have someone else send credentials to see this person's things (they would only be able to see their own). There are times when this is useful (such as when you are a customer rep), but your use case may not require it. Regardless, that has nothing to do with RESTfulness. – Jonathan W Mar 18 '15 at 03:21
  • Further elaboration: http://www.intridea.com/blog/2010/4/29/rest-isnt-what-you-think-it-is – Jonathan W Mar 18 '15 at 03:25
  • Today I've found this answer: https://stackoverflow.com/a/24308290/167196. So what I think is that when using A with the header "Vary: Authorization" you are good – JonHendrix Jul 18 '17 at 18:51

4 Answers4

8

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

Visionscaper
  • 3,979
  • 1
  • 23
  • 26
  • Why does an API user need to semantically understand a URI? If they are doing that, they are not following links and are coding themselves into a URI corner, potentially. Either that or the API is not returning links to begin with, meaning that the API is not RESTful. – Jonathan W Mar 17 '15 at 20:29
  • Hi Jonathan, "Why does an API user need to semantically understand a URI?". To me that is like asking why do we give variables semantically useful names when programming? I do understand your point about the requirement of returning links to the resources, making everything transparent. Imagine that they do return these links, then eventually my question seems to boil down to if semantics are important when defining URIs? I think it is. For the system parsing it not, for the programmer it is. Agree? – Visionscaper Mar 17 '15 at 22:04
  • Nope, sorry. I do not agree. The programmer should be working exclusively to understand well-documented resource relations and really shouldn't care a lick for what the URI looks like. – Jonathan W Mar 18 '15 at 03:16
  • JonathanW, jfcorugedo, @inf3rno I updated my own answer to reflect comments made on the question and answers given. Thanks all for your input and discussion. – Visionscaper Mar 18 '15 at 12:17
  • Thanks for the modifications. Your answer makes a lot more sense now. I still have issues with your assessment of Endpoint A. First, request headers are an integral part of an HTTP request. You cannot determine simply exclude them from an idempotency discussion. What if you change the Accept header, for instance, or what if HTTP Basic is *required*? – Jonathan W Mar 18 '15 at 14:16
  • 1
    I would also argue that, for endpoint A, you always want to get the thing for the currently logged in user and that this is desirable. Consider https://inbox.google.com for instance. If I share this link with you, my intent is almost assuredly *not* to give you access to my inbox, but rather to give you a reminder of where *your* inbox is. That may be the only requirement you have. And, if you ever need to give additional access, there is nothing saying that you can't also create a B/C style endpoint in the future to enable that behavior. – Jonathan W Mar 18 '15 at 14:18
2

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

Roj
  • 334
  • 4
  • 10
1

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://www.rfc-editor.org/rfc/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.

Community
  • 1
  • 1
inf3rno
  • 24,976
  • 11
  • 115
  • 197
  • Hi @inf3rno, I'm not sure if you are answering my questions. In the case of endpoint A the *representation* of the returned resources stay the same but *which* resources are returned differ depending who authorises. If I read your first paragraph correctly you are saying that this is unwanted behaviour, correct? And if so, is it just bad URI design or does it actually violate REST principles? – Visionscaper Mar 12 '15 at 21:58
  • @Visionscaper Ofc. I did not answer your question, because they does not make sense in this context. I edited my answer maybe it is easier to understand now. – inf3rno Mar 12 '15 at 22:49
  • Hi @inf3rno can you explain why my question don't make sense? I explain how the potential endpoints are defined and how they behave. Then I ask if they are designed in a RESTful way and if the URI designed well. I don't see what is wrong with that. To be sure, I improved the text of my question, also to make the focus of my questions clearer : API endpoints that differentiate which resources are returned depending who authenticates, NOT which representation is returned. Thanks for you time! – Visionscaper Mar 13 '15 at 10:23
  • 1) Thanks for the link to the dereferencable URIs, it was useful. Does this imply that endpoint A should at least be defined as, e.g., /things/list in order to deference it (in this case) as a list? – Visionscaper Mar 13 '15 at 10:37
  • 2) Indeed, when only the representation changes depending on auth details, then no URI should be defined. I agree. But IMHO that does not answer my question. My question is about URI design and RESTfulness when the resource instance returned change, not the representation. – Visionscaper Mar 13 '15 at 10:41
  • 3) Interestingly enough, I never see this type of dereferenceable URI designs used in practice. For instance, the Twitter REST API [1] defines GET statuses/retweets/:id and not statuses/retweets/:id/tweet or statuses/retweets/:id#tweet. Facebook's GRAPH API [2] uses GET /me/photos and not /me/photos/list or /me/photos#list The Google Plus API [3] defines GET /people/userId and not GET /people/userId/person or /people/userId#person Are they all not following wrong? [1] http://bit.ly/1Eh5Tw4 [2] http://bit.ly/1CbAnRe [3] http://bit.ly/1f8xrIE – Visionscaper Mar 13 '15 at 10:56
  • @Visionscaper 1.) It means that you have to distinguish between THINGs (I'll use uppercase by real word things hereafter) and the web documents which can describe them. The web documents are dereferencable , but the THING URIs are not. You can use the `/things` if you want to serve the web documents. There is no constraint about that, since there is no strong constraint about what URI structure to use. You can use even meaningless URIs if you want, because you have to follow the [HATEOAS constraint](http://en.wikipedia.org/wiki/HATEOAS). So the links MUST be meaningful to the clients. – inf3rno Mar 13 '15 at 12:17
  • @Visionscaper 3.) This is because those are not THINGs, but web documents they describe. For example `/users/inf3rno/profile` can have a link with the URI `/users/inf3rno/profile#person` which is a relation to me and is not dereferencable. While the `/users/inf3rno/profile` is a profile page of me, which is dereferencable. It is not clear that your are talking about THINGs or just web documents which you call as "things". – inf3rno Mar 13 '15 at 12:21
  • @Visionscaper 2.) I suggest you to read the Fielding dissertation: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm at least the section about REST. It will be easier to understand what REST is. According to the uniform interface constraint every URI structure is RESTful as long as it meets with the URI standard http://www.w3.org/Addressing/. In you case the RESTfulness of the URIs depends on whether you are talking about THINGs or just web documents, since THING URIs are not dereferanceable. – inf3rno Mar 13 '15 at 12:28
  • thanks for your answers. In my questions, own answer and comments I was of course talking about web documents of the resources, e.g. JSON objects providing properties of the resource instances. – Visionscaper Mar 13 '15 at 12:41
  • 3
    @Visionscaper All of A.) B.) C.) are good URI designs. I prefer A.) to list the whole collection (an empty collection if no credentials given) and a partial collection (if credentials given, but no rights to list the whole collection). If somebody else (or the user herself) wants to list the things owned by another user, then use B.) or C.). Ofc. you have to add meta-data like things and owned-things to the links, so the client will know what the links mean. You can use either dereferencable or non-dereferencable URIs to describe these terms. The URIs can point to the developer documentation. – inf3rno Mar 13 '15 at 13:11
0

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).

jfcorugedo
  • 9,793
  • 8
  • 39
  • 47
  • Hi jfcorugedo, thanks for your answer. I found the remark about engines not caching request with query parameters helpful! However, IMHO you are not answering my questions. I improved the text of my question to make the focus of my questions clearer : It is about 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. Your feedback is welcome! – Visionscaper Mar 13 '15 at 10:15
  • 1
    Ok, in this case I think it's ok to send the user a different representation based on security. However, be careful when the user bookmark your urls – jfcorugedo Mar 16 '15 at 22:11