Reputation: 17057
I have just noticed something I didn't expect. I've been trying to "grok" it for a while, but didn't quite manage. It's driving me insane...
Take the standard Expressjs file. I added something:
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, http = require('http')
, path = require('path');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.post( '/call/loginAnon', function(req,res, next){
console.log("IN THE CALL! %j %j %j", req.path, req.body, req.headers );
next();
});
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
app.get('/', routes.index);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
I also added a debug line to bodyParser.js so that we know when it's invoked. Note that /call/loginAnon is defined before bodyParser. This is the result:
IN THE CALL! "/call/loginAnon" undefined {"host":"localhost:3000","connection":"keep-alive","content-length":"30","origin":"http://localhost:3000","x-requested-with":"XMLHttpRequest","user-agent":"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1","content-type":"application/json","accept":"application/javascript, application/json","referer":"http://localhost:3000/login","accept-encoding":"gzip,deflate,sdch","accept-language":"en-GB,en-US;q=0.8,en;q=0.6","accept-charset":"ISO-8859-1,utf-8;q=0.7,*;q=0.3","cookie":"sid=s%3ASI%2F9XFcpe2qFdQNrmsL8ihz8.MezqsOBJM%2FWX9BZOJ0za7F1d8UX6sNjmQZBhN3mqFVA"}
Headers IN BODYPARSER.js: /call/loginAnon {"host":"localhost:3000","connection":"keep-alive","content-length":"30","origin":"http://localhost:3000","x-requested-with":"XMLHttpRequest","user-agent":"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1","content-type":"application/json","accept":"application/javascript, application/json","referer":"http://localhost:3000/login","accept-encoding":"gzip,deflate,sdch","accept-language":"en-GB,en-US;q=0.8,en;q=0.6","accept-charset":"ISO-8859-1,utf-8;q=0.7,*;q=0.3","cookie":"sid=s%3ASI%2F9XFcpe2qFdQNrmsL8ihz8.MezqsOBJM%2FWX9BZOJ0za7F1d8UX6sNjmQZBhN3mqFVA"}
IN THE CALL! "/call/loginAnon" {"login":"sd","password":"sd"} {"host":"localhost:3000","connection":"keep-alive","content-length":"30","origin":"http://localhost:3000","x-requested-with":"XMLHttpRequest","user-agent":"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1","content-type":"application/json","accept":"application/javascript, application/json","referer":"http://localhost:3000/login","accept-encoding":"gzip,deflate,sdch","accept-language":"en-GB,en-US;q=0.8,en;q=0.6","accept-charset":"ISO-8859-1,utf-8;q=0.7,*;q=0.3","cookie":"sid=s%3ASI%2F9XFcpe2qFdQNrmsL8ihz8.MezqsOBJM%2FWX9BZOJ0za7F1d8UX6sNjmQZBhN3mqFVA"}
So, my callback ended up getting called twice -- once before bodyparser was called (so req.body
is null
) and once afterwards (with req.body
actually set).
Moving the call underneath bodyParser improved things somewhat:
Headers IN BODYPARSER.js: /call/loginAnon {"host":"localhost:3000","connection":"keep-alive","content-length":"30","origin":"http://localhost:3000","x-requested-with":"XMLHttpRequest","user-agent":"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1","content-type":"application/json","accept":"application/javascript, application/json","referer":"http://localhost:3000/login","accept-encoding":"gzip,deflate,sdch","accept-language":"en-GB,en-US;q=0.8,en;q=0.6","accept-charset":"ISO-8859-1,utf-8;q=0.7,*;q=0.3","cookie":"sid=s%3ASI%2F9XFcpe2qFdQNrmsL8ihz8.MezqsOBJM%2FWX9BZOJ0za7F1d8UX6sNjmQZBhN3mqFVA"}
IN THE CALL! "/call/loginAnon" {"login":"sd","password":"sd"} {"host":"localhost:3000","connection":"keep-alive","content-length":"30","origin":"http://localhost:3000","x-requested-with":"XMLHttpRequest","user-agent":"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1","content-type":"application/json","accept":"application/javascript, application/json","referer":"http://localhost:3000/login","accept-encoding":"gzip,deflate,sdch","accept-language":"en-GB,en-US;q=0.8,en;q=0.6","accept-charset":"ISO-8859-1,utf-8;q=0.7,*;q=0.3","cookie":"sid=s%3ASI%2F9XFcpe2qFdQNrmsL8ihz8.MezqsOBJM%2FWX9BZOJ0za7F1d8UX6sNjmQZBhN3mqFVA"}
IN THE CALL! "/call/loginAnon" {"login":"sd","password":"sd"} {"host":"localhost:3000","connection":"keep-alive","content-length":"30","origin":"http://localhost:3000","x-requested-with":"XMLHttpRequest","user-agent":"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1","content-type":"application/json","accept":"application/javascript, application/json","referer":"http://localhost:3000/login","accept-encoding":"gzip,deflate,sdch","accept-language":"en-GB,en-US;q=0.8,en;q=0.6","accept-charset":"ISO-8859-1,utf-8;q=0.7,*;q=0.3","cookie":"sid=s%3ASI%2F9XFcpe2qFdQNrmsL8ihz8.MezqsOBJM%2FWX9BZOJ0za7F1d8UX6sNjmQZBhN3mqFVA"}
Still called twice. However, at least this time it had req.body set.
Moving it underneath the end of app.configure actually fixes all of it:
Headers IN BODYPARSER.js: /call/loginAnon {"host":"localhost:3000","connection":"keep-alive","content-length":"30","origin":"http://localhost:3000","x-requested-with":"XMLHttpRequest","user-agent":"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1","content-type":"application/json","accept":"application/javascript, application/json","referer":"http://localhost:3000/login","accept-encoding":"gzip,deflate,sdch","accept-language":"en-GB,en-US;q=0.8,en;q=0.6","accept-charset":"ISO-8859-1,utf-8;q=0.7,*;q=0.3","cookie":"sid=s%3ASI%2F9XFcpe2qFdQNrmsL8ihz8.MezqsOBJM%2FWX9BZOJ0za7F1d8UX6sNjmQZBhN3mqFVA"}
IN THE CALL! "/call/loginAnon" {"login":"sd","password":"sd"} {"host":"localhost:3000","connection":"keep-alive","content-length":"30","origin":"http://localhost:3000","x-requested-with":"XMLHttpRequest","user-agent":"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1","content-type":"application/json","accept":"application/javascript, application/json","referer":"http://localhost:3000/login","accept-encoding":"gzip,deflate,sdch","accept-language":"en-GB,en-US;q=0.8,en;q=0.6","accept-charset":"ISO-8859-1,utf-8;q=0.7,*;q=0.3","cookie":"sid=s%3ASI%2F9XFcpe2qFdQNrmsL8ihz8.MezqsOBJM%2FWX9BZOJ0za7F1d8UX6sNjmQZBhN3mqFVA"}
This is what I've always done (and what most people would always ever done). I just happened to define a route before configure and noticed the weirdness.
I am sure this is due to me not understanding properly the nature of how expressJs works when defining routes. But... can somebody shed some lights on this?
Thanks,
Merc.
Upvotes: 1
Views: 552
Reputation: 3008
The reason why your path is accessed multiple times is that you defined the handler before the app.router middleware.
The reason is that middleware will be used in the order it is defined, with each layer either responding to the request or sending it to the next layer. So explaining your example:
// The handler is defined before the router so any request that passed the
// previous middleware will also be passed into this middleware
// The method (GET or POST or..) or the path is irrelevant at this point
app.post( '/call/loginAnon', function(req,res, next){
// Will run every time
console.log("IN THE CALL! %j %j %j", req.path, req.body, req.headers );
next(); // It is sent to the next middleware layer
});
// Now the bodyParsel will parse the body and give you the req.body variable
app.use(express.bodyParser());
app.use(express.methodOverride());
// This handler will now parse the path of the request and redirect it
// to the defined handler which is why it is accessed the second time
app.use(app.router);
Upvotes: 5