[node.js] Using routes in Express-js

So I'm starting to use Node.js. I saw the video with Ryan Dahl on Nodejs.org and heard he recommended Express-js for websites.

I downloaded the latest version of Express, and began to code. I have a fully fledged static view up on /, but as soon as I try sending parameters, I get errors like this:

Cannot GET /wiki

I tried following the guide on expressjs.com but the way one uses routes has changed in the latest version, which makes the guide unusable.

Guide:

app.get('/users/:id?', function(req, res, next){
    var id = req.params.id;
    if (id) {
        // do something
    } else {
        next();
    }
});

Generated by Express:

app.get('/', routes.index);

My problem arises when I try and add another route.

app.get('/wiki', routes.wiki_show);

I've tried a bunch of approaches, but I keep getting the Cannot GET /wiki (404) error.

routes/index.js looks like this:

exports.index = function(req, res) {
    res.render('index', { title: 'Test', articles: articles, current_article: current_article, sections: sections })
};

The only thing I did there was add some parameters (arrays in the same file) and this i working. But when I copy the contents and change exports.index to exports.wiki or exports.wiki_show I still get the Cannot GET /wiki error.

Can anyone explain to me what I'm missing here? - Thanks.

This question is related to node.js url-routing express

The answer is


You could also organise them into modules. So it would be something like.

./
controllers
    index.js
    indexController.js
app.js

and then in the indexController.js of the controllers export your controllers.

//indexController.js
module.exports = function(){
//do some set up

var self = {
     indexAction : function (req,res){
       //do your thing
}
return self;
};

then in index.js of controllers dir

exports.indexController = require("./indexController");

and finally in app.js

var controllers = require("./controllers");

app.get("/",controllers.indexController().indexAction);

I think this approach allows for clearer seperation and also you can configure your controllers by passing perhaps a db connection in.


Seems that only index.js get loaded when you require("./routes") . I used the following code in index.js to load the rest of the routes:

var fs = require('fs')
  , path = require('path');

fs.readdirSync(__dirname).forEach(function(file){
  var route_fname = __dirname + '/' + file;
  var route_name = path.basename(route_fname, '.js');
  if(route_name !== 'index' && route_name[0] !== "."){ 
    exports[route_name] = require(route_fname)[route_name];
  }
});

The route-map express example matches url paths with objects which in turn matches http verbs with functions. This lays the routing out in a tree, which is concise and easy to read. The apps's entities are also written as objects with the functions as enclosed methods.

var express = require('../../lib/express')
  , verbose = process.env.NODE_ENV != 'test'
  , app = module.exports = express();

app.map = function(a, route){
  route = route || '';
  for (var key in a) {
    switch (typeof a[key]) {
      // { '/path': { ... }}
      case 'object':
        app.map(a[key], route + key);
        break;
      // get: function(){ ... }
      case 'function':
        if (verbose) console.log('%s %s', key, route);
        app[key](route, a[key]);
        break;
    }
  }
};

var users = {
  list: function(req, res){
    res.send('user list');
  },

  get: function(req, res){
    res.send('user ' + req.params.uid);
  },

  del: function(req, res){
    res.send('delete users');
  }
};

var pets = {
  list: function(req, res){
    res.send('user ' + req.params.uid + '\'s pets');
  },

  del: function(req, res){
    res.send('delete ' + req.params.uid + '\'s pet ' + req.params.pid);
  }
};

app.map({
  '/users': {
    get: users.list,
    del: users.del,
    '/:uid': {
      get: users.get,
      '/pets': {
        get: pets.list,
        '/:pid': {
          del: pets.del
        }
      }
    }
  }
});

app.listen(3000);

No one should ever have to keep writing app.use('/someRoute', require('someFile')) until it forms a heap of code.

It just doesn't make sense at all to be spending time invoking/defining routings. Even if you do need custom control, it's probably only for some of the time, and for the most bit you want to be able to just create a standard file structure of routings and have a module do it automatically.

Try Route Magic

As you scale your app, the routing invocations will start to form a giant heap of code that serves no purpose. You want to do just 2 lines of code to handle all the app.use routing invocations with Route Magic like this:

const magic = require('express-routemagic')
magic.use(app, __dirname, '[your route directory]')

For those you want to handle manually, just don't use pass the directory to Magic.


Examples related to node.js

Hide Signs that Meteor.js was Used Querying date field in MongoDB with Mongoose SyntaxError: Cannot use import statement outside a module Server Discovery And Monitoring engine is deprecated How to fix ReferenceError: primordials is not defined in node UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.62.dylib error running php after installing node with brew on Mac internal/modules/cjs/loader.js:582 throw err DeprecationWarning: Buffer() is deprecated due to security and usability issues when I move my script to another server Please run `npm cache clean`

Examples related to url-routing

Get current url in Angular Vue.js redirection to another page AngularJS dynamic routing AngularJS - Animate ng-view transitions Using routes in Express-js RegEx to match stuff between parentheses Routing HTTP Error 404.0 0x80070002 Getting full URL of action in ASP.NET MVC

Examples related to express

UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block jwt check if token expired Avoid "current URL string parser is deprecated" warning by setting useNewUrlParser to true MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017] npm notice created a lockfile as package-lock.json. You should commit this file Make Axios send cookies in its requests automatically What does body-parser do with express? SyntaxError: Unexpected token function - Async Await Nodejs Route.get() requires callback functions but got a "object Undefined" How to redirect to another page in node.js