How can I define express middleware for all routes - node.js

I am trying to define one global middleware which will work for all routes of my app. I tried some ways but still got some issues.
var _gMDLW = function (req, res, next) {
if(req.route) console.log('Called route ', req.route.path);
next();
}
// Working fine and result on _gMDLW is /route1
app.get('/route1', _gMDLW, function (req, res, next) { return res.sendStatus(200); })
var globalRouter = new express.Router()
// Working fine and result on _gMDLW is /view
globalRouter.route('/view')
.get(_gMDLW, function (req, res, next) { return res.sendStatus(200);})
app.use(globalRouter);
But problem is here
// Error in _gMDLW and getting /list instead of /items/list
var itemRouter = new express.Router()
itemRouter.route('/list')
.get(_gMDLW, function (req, res, next) { return res.sendStatus(200);})
app.use('/items', itemRouter)
Second Question is is there any way to define/add _gMDLW inside app instead of adding in each route something like app.use(_gMDLW) ?
Thank you

You can use app.all() to resolve this issue
Example
app.all('*', _gMDLW);
function _gMDLW(req, res, next) {
if (req.path == '/') return next();// redirect to homepage for guest
next();//authenticated user
}
You can modify it as your requirement

Related

NodeJS: route parameter at the first slash works but the same one at the second does not

The file myProject\app.js code is:
app.use('/student', require('./routes/studentsRoutes'));
app.get('/loadexercise', function (req, res) {
let result = {unit: req.query.unit, part: req.query.part};
res.json(result);
});
The file myProject\routes\studentsRoutes.js contains:
var express = require('express');
var router = express.Router();
router.get('/loadexercise', function (req, res) {
let result = {unit: req.query.unit, part: req.query.part};
res.json(result);
});
module.exports = router;
When I run the link http://localhost:55555/loadexercise?unit=1&part=1 from a browser, the render is OK like this: {"unit":"1","part":"1"}.
But when I run the link http://localhost:55555/student/loadexercise?unit=1&part=1, it shows [].
What am I doing wrong?
The request http://localhost:55555/student/loadexercise?unit=1&part=1 will fall into the route /:unit because it has a parameter and this route goes above the route /loadexercise and Express treats loadexercise as a value of the unit parameter.
You simply need to move all routes with static parts before routes with the same part of a route but as a dynamic parameter:
router.get('/loadexercise', function (req, res) {
let result = {unit: req.query.unit, part: req.query.part};
res.json(result);
});
router.get('/login', function(req, res, next) {});
router.post('/login', function(req, res, next) {});
router.get('/changepass', function(req, res, next) {});
router.post('/changepass', function(req, res, next) {});
router.get('/:unit', function (req, res) {
...

Express - using application-level middleware conditionally on route-level

I'm trying to understand how to use an application-level middleware (or at least usually used like this) like cookie-parser on route-level and conditionally.
I tried something like:
const myMiddleware = (req, res, next) => {
if (myCondition) {
return cookieParser();
} else {
next();
}
}
app.use('/admin', myMiddleware, (req, res) => {
res.sendStatus(401)
})
But it's not working, the request will be just stuck.
Is this possible?
Traditional cookie-parser implementation:
app.use(cookieParser())
cookieParser() returns a middleware function, i.e. a function that takes in req, res, next as arguments. You just have to pass it the arguments:
const cookieParserMiddleware = cookieParser();
const myMiddleware = (req, res, next) => {
if (myCondition) {
return cookieParserMiddleware(req, res, next);
}
next();
};
app.use("/admin", myMiddleware, (req, res) => {
res.sendStatus(401);
});
Notice that I'm creating the cookieParser middleware outside myMiddleware - technically we could also just do return cookieParser()(req, res, next) but recreating the same middleware again and again on every request would be wasteful.
I've also removed the else since the if block returns from the function (guard clause).

setting up a middleware in router.route() in nodejs (express)

what I want it to do.
router.post('/xxxx', authorize , xxxx);
function authorize(req, res, next)
{
if(xxx)
res.send(500);
else
next();
}
I want to check for session in each route.
But since the routers are written in this way.
router.route('/xxx/xxxx').post(function(req, res) {
// blah lah here...
//
});
So how can I set up a middleware that will check for session and I wanted to make things a bit more generic and wanted to have a single authorize function doing a single thing instead of checking in every request.Any suggestions.
Define a middlware function before you define / include your routes, this will avoid you checking for a valid session in every route. See code below for an example on how to do this.
If some routes are public, i.e. they do not require a user to have a valid session then define these BEFORE you 'use' your middlware function
var app = require("express")();
//This is the middleware function which will be called before any routes get hit which are defined after this point, i.e. in your index.js
app.use(function (req, res, next) {
var authorised = false;
//Here you would check for the user being authenticated
//Unsure how you're actually checking this, so some psuedo code below
if (authorised) {
//Stop the user progressing any further
return res.status(403).send("Unauthorised!");
}
else {
//Carry on with the request chain
next();
}
});
//Define/include your controllers
As per your comment, you have two choices with regards to having this middleware affect only some routes, see two examples below.
Option 1 - Declare your specific routes before the middleware.
app.post("/auth/signup", function (req, res, next) { ... });
app.post("/auth/forgotpassword", function (req, res, next) { ... });
//Any routes defined above this point will not have the middleware executed before they are hit.
app.use(function (req, res, next) {
//Check for session (See the middlware function above)
next();
});
//Any routes defined after this point will have the middlware executed before they get hit
//The middlware function will get hit before this is executed
app.get("/someauthorisedrouter", function (req, res, next) { ... });
Option 2 Define your middlware function somewhere and require it where needed
/middleware.js
module.exports = function (req, res, next) {
//Do your session checking...
next();
};
Now you can require it wherever you want it.
/index.js
var session_check = require("./middleware"),
router = require("express").Router();
//No need to include the middlware on this function
router.post("/signup", function (req, res, next) {...});
//The session middleware will be invoked before the route logic is executed..
router.get("/someprivatecontent", session_check, function (req, res, next) { ... });
module.exports = router;
Hope that gives you a general idea of how you can achieve this feature.
Express routers have a neat use() function that lets you define middleware for all routes. router.use('/xxxxx', authorize); router.post('/xxxx', 'xxxx'); should work.
Middleware:
sampleMiddleware.js
export const verifyUser = (req, res, next) => {
console.log('Verified')
next();
}
Routes
import express from 'express';
import { verifyUser } from './sampleMiddleware.js';
const userRoutes = express.Router();
userRoutes.route('/update').put(verifyUser, async function(){
//write your function heere
});
You've probably gotten the answer you need but I'll still drop this
router.route('/xxx/xxxx').get(authorize, function(req, res) {...});

Express - public directory divided for authorized/unauthorized users

I have an app written in express.js and I'm trying to divide this application to 2 sections:
one for unauthorized users (with routes only to / - landing page, /login and /* - error404)
and second (routes will be: / - landing page, /app/* - angular SPA which will handle routing on its own)
Express is also configured to take static files from /unauth/public/
And I want to add second static folder for request from authorized routes - /auth/public
which goes to /app/*
My route config looks like this:
var authRoutes = express.Router();
var unauthRoutes = express.Router();
authRoutes.get('/app/*', function(req, res, next) {
if(!req.isAuthenticated())
return res.redirect("/login/");
res.send("AUTHORIZED");
});
unauthRoutes.get('/', function(req, res, next) {
res.send("LANDING PAGE");
});
unauthRoutes.get('/login/', function(req, res, next) {
if(req.isAuthenticated())
return res.redirect("/app/");
res.send("LOGIN PAGE");
});
unauthRoutes.get('/registration/', function(req, res, next) {
if(req.isAuthenticated())
return res.redirect("/app/");
res.send("REGISTRATION PAGE");
});
unauthRoutes.get('/*', function(req, res, next) {
res.send("ERROR 404");
});
app.use('/', authRoutes);
app.use('/', unauthRoutes);
I tried to modify req.url and call another static oruter express.static('auth/public') based on this:
Using express.static middleware in an authorized route
But I don't know, how to handle route app.get('/auth/*', ...) - previous modification will replace url and this route will never be called..
You could try something like this:
// Create your static middlewares
var unauthStatic = express.static('unauth/public');
var authStatic = express.static('auth/public');
// This goes in place of where you would normally load your static middleware
app.use(function(req, res, next) {
if (req.isAuthenticated()) {
authStatic(req, res, next);
} else {
unauthStatic(req, res, next);
}
});
edit:
if you want authenticated users to be able to access files from both the auth and unauth directories, you can make two calls to app.use, like this:
app.use(unauthStatic);
app.use(function(req, res, next) {
if (! req.isAuthenticated()) {
return next();
}
authStatic(req, res, next);
});
Remember that express uses middleware in a stack, meaning to serve a given request, all registered middleware is used in the order it's used. Once a bit of middleware calls req.send, no further middleware gets executed. Anyway, try something like this:
function Authorization(req, res, next) {
if(!req.isAuthenticated())
return res.redirect("/login");
next();
}
var AnonRouter = express.Router()
// GET /style.css will request /unauth/public/style.css
.use(express.static('unauth/public'))
.get('/', function (req, res) { })
.get('/login', function (req, res) { });
var AuthRouter = express.Router()
.use(Authorization)
// GET /app/style.css will request /auth/public/style.css
.use(express.static('auth/public'))
.get('*', function (req, res, next) {
// Handle reqs for non-static files
});
app.use('/', AnonRouter);
app.use('/app', AuthRouter);
app.get('*', function (req, res) {
res.status(404).send('404!');
});
But I don't know, how to handle route app.get('/auth/*', ...) - previous modification will replace url and this route will never be called..
This statement makes me think that you are trying to somehow handle the request after express's static middleware has been called. This is not possible: the static middleware serves static files and you cannot execute additional logic after it does so, but you can run stuff before! Note that in my code, the Authorization middleware will run before the static file is sent.

404 error when Routing using Express and Nodejs

I have created a basic Node/Express App and am trying to implement routes based on separation of logic in different files.
In Server.js
var app = express();
var router = express.Router();
require('./app/routes/users')(router);
require('./app/routes/events')(router);
require('./app/routes/subscribe')(router);
require('./app/routes/login')(router);
app.use('/api',router);
In ./app/routes/users.js
module.exports = function(router){
router.route('/users/')
.all(function(req, res, next) {
// runs for all HTTP verbs first
// think of it as route specific middleware!
})
.get(function(req, res, next) {
res.json(req.user);
})
.put(function(req, res, next) {
// just an example of maybe updating the user
req.user.name = req.params.name;
// save user ... etc
res.json(req.user);
})
.post(function(req, res, next) {
next(new Error('not implemented'));
})
.delete(function(req, res, next) {
next(new Error('not implemented'));
})
router.route('/users/:user_id')
.all(function(req, res, next) {
// runs for all HTTP verbs first
// think of it as route specific middleware!
})
.get(function(req, res, next) {
res.json(req.user);
})
.put(function(req, res, next) {
// just an example of maybe updating the user
req.user.name = req.params.name;
// save user ... etc
res.json(req.user);
})
.post(function(req, res, next) {
next(new Error('not implemented'));
})
.delete(function(req, res, next) {
next(new Error('not implemented'));
})
}
All of the routes are returning 404-Not Found.
Does anyone have suggestions on the best way to implement modular routing in Express Apps ?
Is it possible to load multiple routes in a single Instance of express.Router() ?
------------Edit---------------
On Further Testing
I've been able to debug the express.Router() local instance, and the routing layer stack in the local "router" variable is being updated with the routes from the individual modules.
The last line:
app.use('/api', router);
is also successfully updating the global app instance internal app.router object with the correct routing layers from the local router instance passed to it.
I think the issue is that the Routes for the '/api' are at number 13-14 in the routing layer stack so there is some issue further up the stack with some other middleware routing not letting the routes through to the end... I just need to track this down I guess.
Two issues here :
(1) Looks like the router.route().all was not returning a result, or calling the next() route in the layer.
There is an article here also.
https://groups.google.com/forum/#!topic/express-js/zk_KCgCFxLc
If I remove the .all or insert next() into the .all function, the routing works correctly.
(2) the trailing'/' in the route definition was causing another error
i.e. router.route('/users/') should be router.route('/users')
The slash is important.
Try the following way,
Server.js
app.use('/users' , require('app/routes/users'));
app.use('/events' , require('app/routes/events'));
app.use('/subscribe' , require('app/routes/subscribe'));
In you app/routes/users.js
var router = express.Router();
router.get('/', function (req, res, next) {
//code here
})
router.get('/:id', function (req, res, next) {
//code here
})
module.exports = router;

Resources