0

Was arguing with someone about REST API Design.

I have the routes GET /customers and GET /customers/<c-id> where c-id is the id of a customer.

Now the question is about adding a route for projects.

GET /customers/<c-id>/projects gives all projects of a customer. That someone suggested now to add GET /customers/<c-id>/projects/<p-id> to get information about one specific project. I have a bad feeling about that. Since p-id is a unique id for all projects, the c-id is not needed in the request at all. GET /projects/<p-id> should just do. c-id also is an attribute of the returned project json (every project belongs to just one customer). So this is the main question here: is it consistent with good practice to have the in my opinion superfluous c-id in the request?

One argument from the other side was this example from a blog:

GET /cars/711/drivers/4

But as far a I understand this only applies as good practice if 4 is not a unique identifier, but rather an enumeration in the example (the fourth driver of this car).

Further information:

Actually GET /projects is not used at the moment. So I also thought about adding it and using GET /projects?customerid=<c-id> instead of GET /customers/<c-id>/projects. What do you think about that?

Also the application in question has a permissions layer. So someone who's not allowed to access a specific customer should not be allowed to access projects of this customer, even if he knows the project-id. It was argued that this restriction is better expressed in the GET /customers/<c-id>/projects/<p-id> route. (The permission is actually decided upon a user-id attribute which is a property of customer and project likewise.) Would this change your answer to the question?

daign
  • 899
  • 1
  • 10
  • 18
  • #daign i will go with your suggestion – Vijay Arun Dec 15 '17 at 16:58
  • 1
    First, REST doesn't care about your API design much as the API should provide the client with every information needed to take further actions, nothing more, nothing less. Anything else might only matter to you, the designer/developer of the API. The question therefore may produce opinionated answers and is thus a candidate for being closed as such. Next, if projects ship their own unique identifiers, why not simply declare them as first-class resources `/projects` in first place and just use links from the customer to the project (and/or vice versa)? – Roman Vottner Dec 15 '17 at 17:28
  • Finally found a related question (not easy to think of the right search key words here): https://stackoverflow.com/questions/20951419/what-are-best-practices-for-rest-nested-resources – daign Dec 17 '17 at 11:52

4 Answers4

2

So this is the main question here: is it consistent with good practice to have the in my opinion superfluous c-id in the request?

Sure, why not?

REST doesn't care what spellings you use for URI.

Where I think you are getting tangled up; there is no rule that says each entity in your domain model must have one and only one resource associated with it.

It is perfectly acceptable to have resources like

/customers/<c-id>/projects/<p-id>
/customers/<c-id>/projects/<local-index>
/projects/<p-id>
/9e7b964a-c87a-4184-84b1-24132aabab66

that all map to the same concept in your domain model, and therefore return the same representations, or redirect to each other, or whatever.

It was argued that this restriction is better expressed in the GET /customers//projects/ route. (The permission is actually decided upon a user-id attribute which is a property of customer and project likewise.) Would this change your answer to the question?

No, because identification and security are orthogonal concerns.

Actually GET /projects is not used at the moment. So I also thought about adding it and using GET /projects?customerid= instead of GET /customers//projects. What do you think about that?

Same as before

/customers/<c-id>/projects
/projects?customerid=<c-id>
/a685ee45-f366-462b-a47a-dff61f98dd1e

... are all perfectly reasonable choices.

One thing which you may want to consider is RFC 3986, which specifies the rules for computing a new identifier given a base and a relative reference. Dot segments can be a convenient shorthand for directing the client to another reference without needing to worry about which base identifier is currently in scope.

Community
  • 1
  • 1
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
1

We are discussing here two approaches.

  1. To Divide url as custId + projId *

Yes. I will prefer this approach as well as it will be easy to handle authorization mechanism as compared to another approach.


If this is also case that 3 different customers have same project Id then also this type of structure will be helpful.

  1. To access directly using project Id.

    In this approach you will have to retrieve custId first and then check for authorization.

Rohan Kadu
  • 1,311
  • 2
  • 12
  • 22
  • Project-ids are unique across all customers. Valid point about the authorization. But actually permission is not based upon the customer-id. It's based upon a user-id which is an attribute of every object. I should add this to the question. – daign Dec 15 '17 at 17:31
1

GET /customers/<c-id>/projects/<p-id> looks like a better option:

  • it clearly communicates that every project is assigned to one customer
  • it is clear that only when the user has access to /customers/<c-id> he can call /customers/<c-id>/projects/*
  • the fact that <p-id> are globally unique is an implementation detail and does not have to be communicated in the REST API
Adam Siemion
  • 15,569
  • 7
  • 58
  • 92
0

If your goal is to design a RESTful API which stands the test of time, your clients shouldn't really care what your URLs look like. (i.e. embracing HATEOS) In fact you should insist on your clients not trying to construct URLs based on some form of URL template.

If a client needs to get the list of projects for a customer, your hypertext (i.e. the resource representation returned to the client) should include an URL + instructions on how to do so.

That is how HTML handles it: You get a form URL and various HTML tags that describe how to add parameters to the URL to find a specific resource. That's why you can have a generic client application (the browser) to - for example - a bank. The browser doesn't care what an account is, it just knows how to retrieve resources.

Going full REST is extra work that is worthwhile if you have no control over who your clients (the software making requests to your service) are and you are looking to evolve your API for many years to come without forcing unnecessary changes to your clients.

Jochen Bedersdorfer
  • 4,093
  • 24
  • 26