Discussion regarding default population of REST

Not sure if this is the best way but I’ve managed to set some default population logic for specific collection types using middleware.

For example. If i wanted every request for books to return the author relation without having to worry about providing it in the query string:
Books Router config: /api/book/routes/book.js

module.exports = {
  routes: [
    {
      method: "GET",
      path: "/books",
      handler: "book.find",
      middlewares: ["populate-books"]
    },
    // ... more routes (with the same middleware if you want)
  ]
}

And then in /api/book/middlewares/populate-books.js:

const populateList = ["author"];

const enrichCtx = (ctx) => {
  if (!ctx.query) {
    ctx.query = {};
  }
  const currentPopulateList = ctx.query.populate || [];
  ctx.query.populate = [...currentPopulateList, ...populateList];
  return ctx;
};

module.exports = (config, { strapi }) => {
  return async (context, next) => {
    const newCtx = enrichCtx(context);
    context = newCtx;
    await next();
  };
};

This means that any find request for books will return the author, whether the populate query param has been passed or not. If it has been passed in, it will retain the query that’s been asked for as well as enriching it with authors.

I suppose if you wanted to “reverse” the default populate logic you could change the enrichCtx function only use the query from the request if it’s present, and if not, use the default one you defined?

Not sure if middlewares or policies is the best place for this kind of logic. (Or even if it’s not a good idea in general) :thinking:

Hope that helps someone though!

2 Likes