title: "automatic" routes for express in node.js
body: <p>I'm starting to work with node.js and express for some restful API. I'm breaking my logic up into controllers. Each controller has some methods in to that correspond to what my API is doing. I don't want to have to update my routes every time I add a new functionality to and existing controller or a whole new feature with a new controller. To that end I'm trying to have my restful api defined by a simple set of routes and smart enough to figure things out based on the existing controllers and methods. To that end I have this...</p>
  
  <pre><code>"use strict";
  
  module.exports = function (app) {
      var routes = [
          {
              'get'        : true,
              'put'        : false,
              'post'       : false,
              'update'     : false,
              'delete'     : false,
              'controller' : '',
              'action'     : 'search',
              'url'        : '/:controller/search/:query/:page?'
          },
          {
              'get'        : true,
              'put'        : false,
              'post'       : false,
              'update'     : false,
              'delete'     : false,
              'controller' : '',
              'action'     : '',
              'url'        : '/:controller/'
          },
          {
              'get'        : true,
              'put'        : false,
              'post'       : true,
              'update'     : true,
              'delete'     : true,
              'controller' : '',
              'action'     : '',
              'url'        : '/:controller/:id'
          },
          {
              'get'        : true,
              'put'        : false,
              'post'       : true,
              'update'     : false,
              'delete'     : false,
              'controller' : '',
              'action'     : '',
              'url'        : '/:controller/:id/:action'
          }
      ];
  
      function setupRoute(method, item) {
          if (method in item &amp;&amp; item[method]) {
              console.log('Init route: ' + method.toUpperCase() + ' ' + item.url);
              app[method](item.url, function(req, res) {
                  var c = '';
                  if ('controller' in item) {
                      c = item.controller;
                  }
                  var a = '';
                  if ('action' in item) {
                      c = item.action;
                  }
  
                  if ('controller' in req.params) {
                      c = req.params.controller;
                  }
                  if ('action' in req.params) {
                      a = req.params.action;
                  }
                  if (c == '') {
                      c = 'default';
                  }
                  if (a != '') {
                      a += '_';
                  }
                  a += req.method.toLowerCase();
  
                  c = c.toLowerCase();
                  a = a.toLowerCase();
  
                  if (c in app.controllers) {
                      if (a in app.controllers[c]) {
                          app.controllers[c][a](req, res);
                      } else {
                          console.log('Unknown action on controller ' + a);
                          res.status(400).send('Bad Request');
                      }
                  } else {
                      console.log('Unknown Controller  ' + c);
                      res.status(404).send('Not found');
                  }
              });
          } else {
              app[method](item.url, function(req, res) {
                  res.status(405).send('Method Not Allowed');
              }
          }
      }
  
      routes.forEach(function(item) {     
          setupRoute('get', item);
          setupRoute('put', item);
          setupRoute('post', item);
          setupRoute('update', item);
          setupRoute('delete', item);
      });
  }
  </code></pre>
  
  <p>Are there any problems with setting things up this way? </p>
  
  <p>Is there a better way to go about doing this?</p>