REST API Design: Transitive Inclusion, or Inlining Associated Objects

Transitive Inclusion (Transclusion for short) is a feature of REST APIs useful for clients wishing to get more than just the resource in the URL path, in one request.
We use a query string parameter called inline, or perhaps include, equal to the name of the associated objects to include.

For example, suppose that in a Books API, author objects have associated books.
A request for an author:

GET /authors/12345
{
  "id": 12345,
  "name": "Ralph Ellison"
}

The list of books associated with the author:

GET /authors/12345/books
[
  {
    "id": 1,
    "title": "Invisible Man"
  },
  {
    "id": 2,
    "title": "Juneteenth"
  }
]

We can pass the inline parameter on an author request:

GET /authors/12345?inline=books
{
  "id": 12345,
  "name": "Ralph Ellison",
  "books": [
    {
      "id": 1,
      "title": "Invisible Man"
    },
    {
      "id": 2,
      "title": "Juneteenth"
    }
  ]
}

Note the extra field “books” is included or inlined in the author object.
This way a client app can get the author object and associated books in one request, reducing round-trips. Of course if the objects are small, including the associated objects by default is the best option; this is mostly useful for large, expensive-to-retrieve associated objects.

The transitive inclusion feature can be even more powerful if we get a list of all authors in the API, inlining all of their associated books:

GET /authors?inline=books

Or we can include many associated objects:

GET /authors?include=books,articles

The result is a comprehensive list object, all in one request:

[
  {
    "id": 12345,
    "name": "Ralph Ellison",
    "books": [
      {
        "id": 1,
        "title": "Invisible Man"
      },
      {
        "id": 2,
        "title": "Juneteenth"
      }
    ],
    "articles": [ ... ]
  },
  {
    "id": 67890,
    "name": "Doris Lessing",
    "books": [
      {
        "id": 10,
        "title": "The Golden Notebook"
      },
      {
        "id": 11,
        "title": "The Fifth Child"
      },
      ...
    ],
    "articles": [ ... ]
  },
  ...
]

Such a comprehensive response object can be convenient for an app to build a page listing authors and books, for example; only a single HTTP request can be used .
Note that if the set is large, pagination can be used in addition.

 

Base64 Encode and Decode in Node.js

Using Node on the server side, we find that we cannot use the JavaScript functions atob and btoa. They are not defined; we get the following errors:

ReferenceError: btoa is not defined
ReferenceError: atob is not defined

The functions are defined in JavaScript in the browser, but not in server-side Node.js.

To encode to base-64, instead of btoa use the following:

const myString = 'hello'
const encoded = Buffer.from(myString)
                      .toString('base64')
console.log(encoded)

Output:

aGVsbG8=

To decode from base-64, instead of atob use the following:

const base64String = 'aGVsbG8='
const decoded = Buffer.from(base64String, 'base64')
                      .toString('utf-8')
console.log(decoded)

Output:

hello