I wrote a middleware in express.js/node.js that checks the session and if it finds a user ID, shows the user's menu , or else, the default menu.
Every page request checks for an id and fetches user data from the database (id, name, category etc.)
Here is the middleware:
module.exports = function(req,res,next){
console.log("INSIDE SESSION HANDLER");
if(!req.session.uid) return next();
else{
User.get(uid, function(user){
if (!user) {return next(err);}
else{
req.user = res.locals.user = user;
next();
}
})
}
}
Then, ejs checks locals and if there is an ID, shows the user's menu.
I was loading a testing page that I didnt use the socket.io library, but forgot to delete the <script src="/socket.io/socket.io.js"></script>
line.
<!DOCTYPE html>
<html>
<head>
<title><%= title %> , <%= settings.title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<script src="/socket.io/socket.io.js"></script>//<== SHOULD DELETE THIS
<h1>Login</h1>
<%include menu%> //<== USES EJS TO CHECK LOCALS AND SHOW DEFAULT OR USER MENU
</head>
<body>
When the script src
line was not there the middleware was executing once (saw console.log("INSIDE SESSION HANDLER");
only once).
When the script src
line was there, was giving a 404 error apparently, but the middleware was executing twice ( saw the console.log("INSIDE SESSION HANDLER");
twice).
Here is the output from console.log
:
INSIDE SESSION HANDLER
GET / 304 66ms //page
GET /stylesheets/style.css 304 11ms
INSIDE SESSION HANDLER //again
GET /socket.io/socket.io.js 404 28ms - 1.04kb
GET /multimedia/01.jpg 304 4ms //images...
GET /multimedia/02.jpg 304 5ms
I want to really understand requests/responses and middleware. So why this is happening? Why is this middleware executed twice because of the 404 error? Does the 404 error response cause the middleware to execute twice?
Thanks
EDIT
I use the middleware in app.js like so:
app.use(favicon(__dirname + '/node_modules/static-favicon/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({resave:'false', saveUninitialized:'false', secret:'secret'}));
app.use(express.static(path.join(__dirname, 'public')));
app.set('multimedia', __dirname + '/public/multimedia');
app.use(handler); //<= THE MIDDLEWARE IN QUESTION
app.use(messages);
app.get('/', routes.list);
app.get('/register', register.form);
app.post('/register', register.submitit);
The reason why your middleware is getting run twice is that it is being run once for the initial request, and once for the 404 (the static script that doesn't exist).
If express.static
can find a file, it sends the response with the appropriate file, if it can't find the correct file (as is the case with you) it calls next()
which attempts to match the request to other routes, running any other middleware that are defined below express.static
.
In other words, if express.static
does find the file to serve, middleware below it will not run. In your case the middleware runs once for the actual request and once trying to find the file or a correct route to serve as a response.
This can be observed by logging the req.path
for a normal static file, and one that doesn't exist:
app.js -
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res, next){
console.log('Requested path: %s', req.path);
next();
})
layout.hbs (renders for '/') -
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
<link rel='stylesheet' href='/stylesheets/style.css' /> <!-- exists -->
<link rel='stylesheet' href='/stylesheets/foo.css' /> <!-- doesn't exist -->
</head>
<body>
{{{body}}}
</body>
</html>
We'll see that the middleware will only log the request path for the initial request and for the 404, but not the static file. e.g:
Requested path: /
Requested path: /stylesheets/foo.css
Hope this helps.