8

I tried to separate my node routing into two parts: HTML/App and REST. Here is what I've done:

app.js:

var appPort = process.env.PORT || 80;
var express = require('express');
var http = require('http');
var appRouter = require('./routes/index');
var restRouter = require('./routes/rest');
var app = express();
var srv = http.createServer(app);

app.set('port', appPort);
app.set('view engine', 'jade');
app.use(express.static(path.join(__dirname, 'public')));

app.use('/api/rest/', restRouter); // this seems not working .. I never get the expected response
app.use('/', appRouter);           // I get this even with localhost/api/rest/...

var server = srv.listen(app.get('port'), function() {
    debug('Express server listening  ' + server.address().address + ':' + server.address().port);
});

index.js:

var express = require('express');
var router = express.Router();

router.get('/*', function (req, res) {
    res.send('HOME')
});

module.exports = router;

rest.js

var express = require('express');
var router = express.Router();

router.get('/api/rest/*', function(req, res) {
    res.send('REST API');
});

module.exports = router;

My questions:
1. It's possible in general to build multiple routers in this way?
2. Does the sequence of get.use matter, and/or do I have to deal with 'next'?
3. In case I would like to access a database inside the router can I hand over a parameter like this:

// ...
var client  = new pg.Client(dbConnection);
// ...
app.use('/', appRouter(client));
Machavity
  • 30,841
  • 27
  • 92
  • 100
Rainer
  • 1,067
  • 2
  • 14
  • 29

1 Answers1

10

1) It is possible to build multiple routers this way.

Because you are using this:

app.use('/api/rest/', restRouter);

your route calls in rest.js will be relative to /api/rest/ which means your code should be modified in rest.js to look like this:

router.get('*', function(req, res) {
    res.send('REST API');
});

I would also encourage you to see the Express multi-router example on GitHub. It illustrates this point very clearly by showing a REST app with versioned routes.

2) The order of things matter

See the Express documentation for app.use and you will note:

Middleware functions are executed sequentially, therefore the order of middleware inclusion is important.

If you reverse the order of your app.use calls, the router.get('/*', function (req, res) { line in index.js will catch everything before you get to other routes...defeating your purpose.

Also, if you don't call next, Express has no way to know that you are done or even that you want to continue to the next middleware or route.

3) The database question is a modules/scope question

This is more of a scope question than an Express question. I'd suggest looking up some of the excellent writing about javascript scope and also on how Node handles modules.

Matthew Bakaitis
  • 11,600
  • 7
  • 43
  • 53
  • Thanks Matt, this helps a lot. Let me dig into the mentioned sources, I guess I will get it. – Rainer Dec 05 '14 at 14:58
  • The only remaining question: if sequence matters, and I have app.use(/api/rest/) including next before app.use(/), will the second app.use not catch an api/rest call anyway? – Rainer Dec 05 '14 at 14:58
  • It could potentially match, yes. There are several things that may still halt execution (`res.end` is one, I believe) but if that doesn't happen, Express will move to the next middleware component and run it. – Matthew Bakaitis Dec 05 '14 at 15:12
  • Thanks, it works, I just tried it. After reading the doc's, many things are clearer. Nevertheless: If the middleware functions (app.use) are executed sequentielly (after each http request again?), the second app.use MUST be executed. But it doesn't .. why? Even with putting next into the router functions, I get 'REST API' and not 'HOME' .. I love that's working, but it's not logical to me. – Rainer Dec 05 '14 at 15:33