call app.get inside response.render - express

How can I call another express route inside response.render. Following is my code snippet. I would like to render performance.jade when /pages/performance is requested and populate the jade with data returned from /api/notifications
module.exports = function(app){
app.get('/pages/performance', function(req, res){
res.render("performance", {results: app.get("/api/notifications", function (request, response) {return response.body;}), title: "Performance"});
});
};
/api/notifications will return json data which is then used in jade as follows:
block pageContent
for result in results
p #{result.message}

Make a function that gets the notifications and passes them to a callback. Then use that function in both routes. You can code that either as a pure function or as a connect middleware.
Pure Function
function loadNotifications(callback) {
database.getNotificiations(callback)
}
app.get('/api/notifications', function (req, res) {
loadNotifications(function (error, results) {
if (error) { return res.status(500).send(error);
res.send(results);
}
});
app.get('/pages/performance', function (req, res) {
loadNotifications(function (error, results) {
if (error) { return res.status(500).send(error);
res.render('performance', {results: results});
});
});
Middleware
function loadNotifications(req, res, next) {
database.getNotificiations(function (error, results) {
if (error) { return next(error);}
req.results = results;
next();
});
}
app.get('/api/notifications', loadNotifications, function (req, res) {
res.send(req.results);
});
app.get('/pages/performance', loadNotifications, function (req, res) {
res.render('performance', {results: req.results});
});

Related

ExpressJS mixing middleware arguments with custom arguments

I'm writing a function to create errors and I want to use express' next() function. I have seen working examples using a nested function but my code isn't reached. This is what I have:
/middleware.js
import { errorCreator } from './helper.js';
const middleWare = async (req, res, next) => {
if (!req.headers.header) {
errorCreator('Not Authorized', 401);
}
// More async code here
};
and
/helpers.js
export const errorCreator = (message, statusCode) => {
// this is reached <-----------------
return (req, res, next) => {
// this is not reached <---------------
const error = new Error(message);
error.status = statusCode;
throw error;
};
};
Why do I not reach the nested function?

Why am I not getting a response from express server?

Sending a logout request to my server but I'm never getting a reply. The logout function is being called and the userID key is being deleted from my redis cache but I never get a response. Here's my code.
export const logout = async (req, res) => {
console.log("logout called");
const { userID } = req.user;
client.del(userID.toString, (err, reply) => {
console.log("inside client.del");
if (err) {
return res.status(500);
} else {
return res.status(200);
}
});
};
Because of callback, you should use promise
export const logout = async (req, res) => {
return new Promise((resolve,reject) => {
console.log("logout called");
const { userID } = req.user;
client.del(userID.toString, (err, reply) => {
console.log("inside client.del");
if (err) {
reject(res.status(500));
} else {
resolve(res.status(200));
}
});
});
}
res.status() does not send a response from the server. All it does is set the status as a property on the response object that will go with some future call that actually sends the response.
It is meant to be used in something like this:
res.status(500).send("Database error");
If you look at the Express doc for res.status(), you will see these examples:
res.status(403).end()
res.status(400).send('Bad Request')
res.status(404).sendFile('/absolute/path/to/404.png')
And, see that they all are followed by some other method that actually causes the response to be sent.
And, if you still had any doubt, you can look in the Express code repository and see this:
res.status = function status(code) {
this.statusCode = code;
return this;
};
Which shows that it's just setting a property on the response object and not actually sending the response yet.
You can use res.sendStatus() instead which will BOTH set the status and send the response:
export const logout = (req, res) => {
console.log("logout called");
const { userID } = req.user;
client.del(userID.toString, (err, reply) => {
console.log("inside client.del");
if (err) {
res.sendStatus(500);
} else {
res.sendStatus(200);
}
});
};
Note, I removed the two return keywords since they don't accomplish anything useful in this particular context.
I also removed the async keyword from the function definition since it was not doing anything useful in this context.

Cleaner way to write api route handlers in NextJS

Currently most of the api route handlers are in the following shape(api/test.js):
export default function handler(req, res) {
if (req.method === 'POST') {
// Process a POST request
} else {
// Handle any other HTTP method
}
}
where we constantly compare req.method with ifs
Is there a way to write it similar to ExpressJS:
app.get(...)
import nextConnect from 'next-connect';
const handler = nextConnect();
//handler.use(middleware);
handler.get(async (req, res) => {
...your code
})
...
handler.post(async (req, res) => {
...your code
})
...
So in theory you can have /api/product where you have .get .post .delete (etc) in 1 api route
Clean solution (/api/product.js)
const handler = async (req, res) => {
try {
}
catch(e){
}
}

Axios interceptor use express req object

I have an express route in which I send a header from the front end, in this route I'm making a GET request using axios. I created an interceptor with axios, but I would like to be able to read the req object from the activated route in order to add the header to the axios GET call.
// Example Interceptor
axios.interceptors.request.use(
config => {
// How to get req.headers from the route here?
return config;
},
error => {
return Promise.reject(error);
}
);
// Exemple GET route
router.get('/get', async (req, res, next) => {
try {
const { data } = await axios.get('https://kjhf.fsadjhfewq.....');
} catch (error) {
console.log(error)
}
res.status(200).json({});
});
Is it possible to do this?
So I think the way to do this is to use a middleware to set the headers, and pass on the axios instance
// apiSetHeader.js middleware
exports.default = (req, res, next) => {
req.CustomAxios = axios.create({
headers: { 'HeaderForTheApi': req.headers.apiHeader'}
})
next()
}
And then use that in your route
// Exemple GET route
router.get('/get', apiSetHeaderMiddleware, async (req, res, next) => {
try {
const { data } = await req.CustomAxios.get('https://kjhf.fsadjhfewq.....');
} catch (error) {
console.log(error)
}
res.status(200).json({});
});
Hope this helps!

Express Passportjs Authenticate not being reached in router callback

If I pass passport.authenticate("local") as middleware into my route, it executes. But this way I do not have access to res so I can send a message back to my front end. However, if I attempt to call it in the route callback function, it is not firing.
router.post("/login", function(req, res, next) {
passport.authenticate("local", function(err, user, info) {
console.log("Unreached"); // This is not logging
});
})
Here is my passport.use inside app.js
passport.use(new LocalStrategy({
usernameField: "portalId"
}, function(portalId, enteredPassword, done) {
var params = {
TableName: "MyTableName",
KeyConditionExpression : "PortalID = :portalID",
ExpressionAttributeValues : {
":portalID" : Number(portalId)
}
}
docClient.query(params, function(err, user) {
if (err) throw err;
let realPassword = user.Items[0].password;
bcrypt.compare(enteredPassword, realPassword, function(err, res) {
if (err) throw err;
if (res) {
return done(null, user);
}
if (!res) {
return done(null, false, { message: "Invalid Credentials" });
}
})
})
}));
Saw in some other post a snippet of code using the custom callback and he had (req, res, next) right after the passport.authenticate function. I added this and my code was being fired now.