REST API – Can Multiple Resources Be Returned as One Compound Resource?

resourcesrestweb-api

I'm in the progress of creating a REST API and currently, I'm encountering the following problem:

  • Foo is the first resource. CRUD operations can be applied via the /foo/ URI.
  • Bar is the second resource. CRUD operations can be applied via the /bar/ URI.
  • Every Foo is associated with zero or one Bar. The reason why I don't treat Bar as a subresource of Foo is because the same Bar instance can be shared between mutiple Foos. So I figured it's better to access it via an independent URI instead of /foo/[id]/bar.

My problem is that in a significant amount of cases, clients which ask for a Foo instance are also interested in the associated Bar instance. Currently, this means that they have to perform two queries instead of one. I want to introduce a way that allows to get both objects with one single query, but I don't know how to model the API for doing that. What I came up with so far:

  • I could introduce a query parameter similar to this: /foo/[id]?include_bar=true. The problem with this approach is that the resource representation (e.g. the JSON structure) of the response would need to look different (e.g. a container such as { foo: ..., bar: ... } instead of just a serialized Foo), which makes the Foo resource endpoint "heterogeneous". I don't think that's a good thing. When querying /foo, clients should always get the same resource representation (structure), regardless of query parameters.
  • Another idea is to introduce a new read-only endpoint, e.g. /fooandbar/[foo-id]. In this case, it's no problem to return a representation like { foo: ..., bar: ... }, because then it's just the "official" representation of the fooandbar resource. However, I don't know if such a helper endpoint is really RESTful (this is why I wrote "can" in the title of the question. Of course it's technically possible, but I don't know if it's a good idea).

What do you think? Are there any other possibilities?

Best Answer

A level 3 REST API would return you a Foo and also a link indicating the related Bar.

GET /foo/123
<foo id="123">
  ..foo stuff..
  <link rel="bar" uri="/bar/456"/>
</foo>

You could then add a "drill down" feature to your API which allows the navigation of links;

GET /foo/123?drilldown=bar
<foo id="123">
  ..foo stuff..
  <link rel="bar" uri="/bar/456">
    <bar id="456">
      ..bar stuff...
    </bar>
  </link>
</foo>

The drill down feature would sit in front of the APIs and intercept responses. It would make the drill down calls and fill in the details before handing the response back to the caller.

This is a pretty common thing in level 3 REST as it much reduces client/server chattiness over slow http. The company I work for produces a level 3 REST API with exactly this feature.

Update: For what its worth, here's how it might look in JSON. This is how our API would structure it. Note that you can nest your drill downs to pull links of links etc.

GET /foo/123?drilldown=bar

{
  "self": {
    "type": "thing.foo",
    "uri": "/foo/123=?drilldown=bar",
    "href": "http://localhost/api/foo/123?drilldown=bar"
  },
  "links": [
    {
      "rel": "bar",
      "rev": "foo",
      "type": "thing.bar",
      "uri": "/bar/456",
      "href": "http://localhost/api/bar/456"
    }
  ],
  "_bar": [
    {
      "self": {
        "type": "thing.bar",
        "uri": "/bar/456",
        "href": "http://localhost/api/bar/456"
      },
      "links": [
        {
          ..other link..
        },
        {
          ..other link..
        }
      ]
    }
  ]
}
Related Topic