Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set default resource #22

Open
AdamQuadmon opened this issue May 11, 2014 · 4 comments
Open

Set default resource #22

AdamQuadmon opened this issue May 11, 2014 · 4 comments

Comments

@AdamQuadmon
Copy link

I'm trying to have synth returning a default resource.

The following code in the back/back-app.js works, is there a better way to do it?

/**
 * Array of available resources.
 * Those resource names should not be used as url slugs for pages.
 *
 * @type {string[]}
 */
var availableResources = ['categories', 'pages'];

var defaultPage = 'home';

/**
 * Return an array of path parts.
 * It removes the first part of the array if it's empty.
 *
 * @param {string} path
 * @returns {Array}
 */
var getPathTokens = function (path) {
  /**
   * Array of url path parts.
   *
   * For a path like `/` it returns an array
   * of two empty strings.
   *
   * For a path like `/my-slug` it returns an array
   * of two strings: ['', 'my-slug']
   *
   * @type {Array}
   */
  var pathTokens = path.split('/');

  if (pathTokens[0] === '') {
    pathTokens = pathTokens.splice(1);
  }

  return pathTokens;
};

synth.app.use(function (req, res, next) {

  var currentPathTokens = getPathTokens(req.originalUrl);

  /**
   * If `currentPathTokens` contains only one element
   * and this element is not one of the available resources
   * it assumes it's a page slug and change the route to point
   * to `/page/slug-name`.
   *
   * If `currentPathTokens[0]` is empty it routes to the default one.
   */
  if (currentPathTokens.length === 1
    && currentPathTokens[0].indexOf(availableResources) === -1) {
    req.url = '/pages/' + (currentPathTokens[0] || defaultPage);
  }

  next();
});
@JonAbrams
Copy link
Owner

That's very clever, you're rewriting the url path on the request. I had planned on adding the ability to define a particular resource as the base resource. This would allow you to reference a page with /page-id instead of /pages/page-id but I hadn't thought through yet on how to do it. I think I'll try out this technique, thanks!

As for whether the above code is good for defining a default result for a particular resource, I suppose if it works then it's great. I like how it's so well commented! An alternative would be to define a exports.getIndex method for the resource, and have it respond with the default response. To avoid duplicating code, you can have that method share a function with the exports.get method. For example:

function fetchPage (db, slug) {
  return db.fetchOne({ slug: slug });
}

exports.getIndex = function (req, res) {
  return fetchPage(req.db, 'home');
};

exports.get = function (req, res) {
  return fetchPage(req.db, req.params.id);
};

I never thought of it before, but I suppose this could be a good feature to bake into Synth. If you don't need an index method for a resource, you can define a default id and call the exports.get method for that instead. Thanks for the suggestion!

@AdamQuadmon
Copy link
Author

What I don't like is the need to define the availableResources and listen on every requests.

If we can just intercept a 404 we can re-route the request to a default resource method.
But I'm not a Express expert.

WDYT?

@JonAbrams
Copy link
Owner

You could do the following:

...
module.exports = synth();

// Catch remaining unhandled requests
synth.app.get('/*', function (req, res) {
  // Send back a 302 redirect
  res.redirect('/pages/home');
});

@AdamQuadmon
Copy link
Author

Cool... I'll try this one, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants