News for hackers. Stuff that matters.
Re:API Design Guide by theptip on Wednesday February 22, 2017 @07:17PM (#13710520)
An interesting design question arrises around nested resources. Google in this doc buys into deep nested structures, e.g. `//calendar.googleapis.com/users/john smith/events/123` (from [1]).

I think this pattern is unambiguously sensible when the child objects are strictly scoped under the parent.

But it's less clear how to represent resources that are shared between multiple parents; for example, what if event 123 can be referenced under another user's API resource as well? If we permit `//calendar.googleapis.com/users/bob/events/123`, now we have multiple URLs referring to the same object, and things can get quite tricky in the implementation.

Django Rest Framework strongly discourages (and makes it quite hard to implement) nested resources, FWIW.

I've found that a policy of only permitting one level of nesting seems to be a good balance for shared objects, e.g.

`//calendar.googleapis.com/users/john smith/events/` returns:

``` [ { url: "/events/123"}, ... ] ```

Interested to know how others have solved this problem.

[1]: https://cloud.google.com/apis/design/resource_names

Re:API Design Guide by combatentropy on Wednesday February 22, 2017 @08:02PM (#13710754)
Here's one way to tackle it, if behind your REST API is an SQL database:

  /schema/table/key
So:

  //www.example.com/calendar/events/123

To address many records, like all that belong to Bob, use the query string instead of purely the path:

  //www.example.com/calendar/events/?user=bob
Re:API Design Guide by theptip on Wednesday February 22, 2017 @11:16PM (#13711584)
This is in my experience the `standard` design; it does give you a lot of freedom to change what filters you allow, and to stack them. Nobody's going to get fired for this design, and there's a lot of prior art around it to draw examples from. It also has the benefit of keeping the API surface small and clean.

But it makes it a bit weird to do HATEOAS; you _could_ do `GET Bob => {events: "calendar/events/?user=bob"}` -- but then you're hyperlinking to a search and not a resource.

It also tells less of a narrative in the structure; `user=bob` is just another filter that you can use to apply to the events set. But we get a chance to describe the shape of the data a bit more if we choose to declare an intermediate resource (/users/) and attach some links to it (=>/users/bob/events).

Now, if there are ten ways that you need to slice your `events` set, and ?user=bob is but one of them, then scoping a sub-resource /users/events/ isn't that useful/descriptive.

As an aside, I think this is where HATEOAS is nice; it makes it very easy to navigate an API as a developer, see what actions are possible at every node, and hopefully learn the intent of the author of the API without having to chew through a set of API documentation. Django Rest Framework's API browser is a great example here.

Re:API Design Guide by absalyamov on Wednesday February 22, 2017 @11:27PM (#13711626)
As described in https://cloud.google.com/apis/design/design_patterns#get_uni...:

  //calendar.googleapis.com/users/-/events/123
Re:API Design Guide by theptip on Wednesday February 22, 2017 @11:49PM (#13711735)
Hadn't spotted that, it's an interesting syntax and I quite like it.

But it doesn't cover the case I'm referring to; in their example you MUST return the fully-qualified URL:

> shelves/shelf713/books/book8141, not shelves/-/books/book8141

This precludes there being multiple shelves with the same book (sensible in their example, since a book has only one shelf, but not in the example above).

Re:API Design Guide by the8bit on Thursday February 23, 2017 @12:09PM (#13715530)
While sometimes this does get tricky with resources that are clearly owned or associated with multiple things, often times a resource only has one real owner and it is unambiguous. It does make moving things a bit weird though, as moving a book between two shelves makes it have a different fully qualified name.
Re:API Design Guide by theptip on Thursday February 23, 2017 @01:39PM (#13716464)
Agree; put another way, sometimes you really do need a M2M relationship.
Re:API Design Guide by joncalhoun on Wednesday February 22, 2017 @10:53PM (#13711486)
I prefer the bare minimum approach. That is, if you NEED the user resource to access the event (eg the primary key is like [user ID, event ID]) then nest it in the url. Otherwise if an object has its own ID and could otherwise be accessed independently why not just do so?
Re:API Design Guide by theptip on Thursday February 23, 2017 @01:40PM (#13716468)
The root of this question is: how do you handle M2M relationships in your API?