Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setup Sails.js routes to support pushstate with a SPA on the frontend

How to setup SailsJS routes to support pushstate, but still be able to serve requests prefixed with /api along with serving static assets as well?

Using:

  • Backbone 1.x with pushState: true
  • Sails 0.10.x

Suggested solution from this thread is to use the /* wildcard and redirect all to the index view.

/path/to/app/config/routes.js

'/*': {
  view: 'index' 
}

The problem is that this will redirect everything to index. including static file assets, the express.static middleware doesn't seem to have an effect, this route is somehow taking precedence.

Also, this prefix below doesn't have any effect, since the route above takes precedence, however the prefix works if I just remove the wildcard i.e '/': { view: 'index' }

/path/to/app/config/blueprint.js

module.exports.blueprints = {
    ...
    prefix: '/api',
    ...
}

Obviously, this does not seem as a core SailsJS issue, but rather my minimal knowledge the expressjs router, since that's what sailsjs is using.

Theoretically, I could explicitly just list out all the assets prefixed routes and have a controller to serve all, since they are well known and static i.e. '/js*': { controller: 'AssetsController', action: 'serve', and so on for '/styles*', '/images*', '/templates*', '/fonts*', but I'm really hesitant on doing so, I'm hoping for a better practice solution.

Also that won't solve this routes /api problem with the wildcard '/*'

like image 508
bentael Avatar asked Mar 31 '14 19:03

bentael


2 Answers

If you're willing to use the development version of Sails from GitHub, you can use the skipRegex route option to let your wildcard route ignore API requests, and the skipAssets option to have it ignore asset URLs:

'/*' : {view: 'index', skipAssets: true, skipRegex: /^\/api\/.*$/}

Otherwise, you can create a controller to serve your view, and add the code to skip unintentionally-matched URLs in the action code:

// api/controllers/StaticController.js
module.exports = {
   index: function(req, res, next) {
      if (req.path.match(/\..*/g) || req.path.match(/^\/api\/.*$/)) {
         return next();
      }
      return res.view('index');
   }
}

Then in /config/routes.js:

'/*': 'StaticController.index'

......

like image 159
sgress454 Avatar answered Nov 19 '22 04:11

sgress454


Try updating your config/404.js file.

  1. Remove the following:

      res.status(result.status);
      res.render(viewFilePath, function (err) {
        // If the view doesn't exist, or an error occured, send json
        if (err) { return res.json(result, result.status); }
    
        // Otherwise, serve the `views/404.*` page
    
        res.render(viewFilePath);
      });
    
  2. Add this: res.redirect("/");

Cheers

like image 1
tUrG0n Avatar answered Nov 19 '22 04:11

tUrG0n