expressjs write multiple middleware and import it to the main file - node.js

I have a script which holds a middleware like:
module.exports = function (req, res, next) {
req.requestTime = Date.now()
next()
}
In a file I can import this but how can I write multiple middleware and export all of them and import it?
I am learning express and got stuck here :)

write multiple middlewares in one file and exprot them all.
function middleware1(req, res, next) { req.requestTime = Date.now(); next() }
function middleware2(req, res, next) { req.requestTime = Date.now(); next() }
function middleware3(req, res, next) { req.requestTime = Date.now(); next() }
module.exports = {
middleware1 : middleware1,
middleware2 : middleware2,
middleware3 : middleware3
}
then if you want to import them you can either import all of middlewares like
var middleware = require("./middlewares")
// name of middleware file in require
then use them like
app.get('/profile', middleware.middleware1, function (req, res) {
// do your stuff
});
Or you can import a single middleware by adding middleware function name in require
var middleware1 = require("./middlewares").middleware1
then use them like
app.get('/profile', middleware1, function (req, res) {
// do your stuff
});

I was trying to do the same, but my scenario was a bit different
I had type module in package.json
{
"type": "module"
}
middleware file and exporting
const authenticate_middleware = (req, res, next) => {
const authHeader = req.headers.authorization;
if (authHeader) {
const items = authHeader.split(' ');
/*check count 2*/
/*check 1st item is barner*/
/*check and validate 2nd item*/
const token = items[1];
let user = {
id: 1,
token: token
}
req.user = user;
next();
} else {
res.sendStatus(401);
}
};
const developer_middleware = (req, res, next) => {
const authHeader = req.headers.developer; /*all lower case apiKey was undefined*/
if (authHeader) {
let developer = {
id: 1,
apiKey: authHeader
}
req.developer = developer;
next();
} else {
res.sendStatus(401);
}
};
export default authenticate_middleware;
export let authenticate = authenticate_middleware;
export let developer = developer_middleware;
importing modulewares
//import multiple
import { authenticate, developer } from '../middlewares/all.js'
//import single
import { developer } from '../middlewares/all.js'
// import default
import authenticate from '../middlewares/all.js'

Related

why i am getting undifine when i console req.query?

this is api.js file
function apiKey(res, req, next) {
const api_key = '12345678';
console.log(req.query);
next();
}
module.exports = apiKey;
You named it wrong way. should be like this
function apiKey(req, res, next) {
const api_key = '12345678';
console.log(req.query);
next();
}
module.exports = apiKey;

error message occur when im trying redirecting the user on server side

im trying to redirect the user to the dashboard if ever the id is not on database.
but I get an error message saying "Cannot set headers after they are sent to the client"
my middleware code
const mongoose = require('mongoose');
const Room = require('./model/room');
module.exports.isOnDB = async (req, res, next) => {
const { id } = req.params;
console.log(id);
const room = Room.findById(id, function (err) {
console.log('ge');
//console.log(err.message);
res.redirect('/');
});
next();
};
my routes code
const { isOnDB } = require('../middleware');
router.get('/', (req, res) => {
res.render('layouts/boilerplate');
});
router.get('/room/:id', isOnDB, (req, res) => {
res.render('room', { roomId: req.params.room });
});
my app.js
const adminRoutes = require('./routes/admin');
app.use('/', adminRoutes);
The problem is that you are not waiting for your Room.findById function to finish before calling next(). I would move the next() call into the Room.findById callback so you can handle both situations - if the id is in the DB and if it isn't.
For example:
module.exports.isOnDB = async (req, res, next) => {
const { id } = req.params;
const room = Room.findById(id, function (err) {
if (err) {
// if id is NOT found, or if there's an error, call next()
console.log(err);
return next();
}
// if the id is found in the DB, then redirect
res.redirect('/');
});
};

Express static with Middleware require login

I created two uploads folder are public and private. Public folder does not require auth but private folder will require a middleware to access;
app.use('/uploads', express.static('uploads/public/'));
app.use('/uploads', require('./admin/routers/api/accessPrivate'), express.static('uploads/private/'));
And here is my accessPrivate
const userPermission = require("../../middleware/permission");
const auth = require('../../middleware/auth');
const accessMedia = async ( req, res, next) => {
await auth(req, res, next);
next();
};
module.exports = accessMedia;
But it shows error: "No token". It means that there is no req header sent to server; Can you tell me how to do?
Thank you so much;
Define a general middleware for all uploads requests. Check the user's permission.
app.use('/uploads', async (req, res, next) => {
let hasAccess = await auth(req, res, next);
if (hasAccess) {
app.use(express.static('uploads/private/'));
}
else {
app.use(express.static('uploads/public/'));
}
next();
});
// your routes
app.use('*', function (req, res, next) {
let target = 'index.html';
if (req.baseUrl && req.baseUrl != '/') {
target = req.baseUrl;
}
if(req.user) {
root = 'uploads/private/';
}
else {
root = 'uploads/public/';
}
res.sendFile(target, { root: root })
});
Also you should change the auth implementation.

How to use csurf within a custom middleware?

I have managed to get csurf working in my express app as a regular middleware. However, I'd like to add it to my custom authentication middleware to both avoid having to include csurf in every route and also to avoid forgetting to use it. How should I call csurf within a custom middleware?
For example, say I have this middleware using express-session to limit access to logged-in users:
export const auth = async (req, res, next) => {
const { uid } = req.session;
try {
const user = await User.query().findById(uid);
req.session.role = user.role;
next();
} catch {
throw new PrivateRouteError();
}
};
This answer has a way of doing this but I was unable to implement it. Here's what I tried:
export const auth = async (req, res, next) => {
const csrf = csurf({ cookie: true, ignoreMethods: [] });
csrf(req, res, async () => {
const { uid } = req.session;
try {
const user = await User.query().findById(uid);
req.session.role = user.role;
next();
} catch {
throw new PrivateRouteError();
}
});
};
However, the result is that csurf does not block access for a missing CSRF token and the PrivateRouteError is not caught and crashed the app (if the user has not authenticated, if they are it works fine).
Is there a neat way to bundle csurf into my middleware or should I just manually add it to all the routes that use the auth middleware?
Okay, I was clearly overthinking this last night. It's enough to get rid of the next() call and put csurf stuff after the catch block.
export const auth = async (req, res, next) => {
const { uid } = req.session;
try {
const user = await User.query().findById(uid);
req.session.role = user.role;
} catch {
throw new PrivateRouteError();
}
const csrf = csurf({ cookie: true, ignoreMethods: [] });
csrf(req, res, next);
};

How to mock Express JWT unless function?

I'm using Express and Express-JWT.
In a Express() instance I use:
const api = express()
api.use(jwt({
// my options
}))
To mock this in tests, I use a mocks\express-jwt\index.js file containing:
const jwt = jest.fn().mockImplementation(options => (req, res, next) => {
// set dummy req.user and call
next()
})
module exports = jwt
This all works fine.
Now I want to skip JWT for the root endpoint, so I changed the jwt usage to:
api.use(jwt({
// my options
}).unless({path:['/']}))
In my mock file I added:
jwt.unless = jest.fn().mockImplementation(options => (req, res, next) => {
next()
})
However, the tests now always fail with function unless is not defined.
Anyone an idea how to mock this unless behaviour?
unless is being used as a property on the result of calling jwt.
So to mock it, add your unless mock as a property of the function returned by your jwt mock:
const jwt = jest.fn().mockImplementation(options => {
const func = (req, res, next) => {
// set dummy req.user and call
next();
};
func.unless = jest.fn().mockImplementation(options => (req, res, next) => {
next();
});
return func;
});
module.exports = jwt;
Suggested answer by Brian did not work for me, because in the func method I do some stuff for faking an authorization check.
My problem was I needed to do skip the authorization check for the method+path given in by the unless function.
My solution now is like this:
const jet = jest.fn(options => {
let mockFunc = (req, res, next) => {
// get authorization from request
let token = ...
if (!token) {
res.status(401).send('No token provided')
} else {
req.token = token
next()
}
}
mockFunc.unless = jest.fn(args => (req, res, next) => {
if (args.method == req.method && arg.path == req.path) {
// not do authorization check for excluded endpoint via unless
next()
else {
mockFunc(req, res, next)
}
}
return mockFunc
}
Thanks to Brian for pointing me in the right direction.

Resources