I have 2 routers
router1
app.post ('/ consultations', function (req, res) {
req.session.nombre = 'administrator';
console.log ('test', req.session.name); // there the session is saved well
});
router2
router.get ('/', function (req, res) {
console.log ('retrieve session', req.session); // exit undefined
}
How can I get the session on the two routers?
EDIT:
i created a middleware
function mymiddleware(req,res,next){
req.session.nombre='MiNOMBRE';
}
and I try to get the middleware;
app.get('/miroute1',mymiddleware,(req,res) => {
console.log(req.session.nombre);//
but never enters
}
app.get('/miroute2',mymiddleware,(req,res) => {
console.log(req.session.nombre);//
but never enters
}
function mymiddleware(req,res,next){
req.session.nombre='MiNOMBRE';
next();
}
next() will call next middleware in sequence, which in your case is
(req,res) => {
console.log(req.session.nombre);}
I think in your middleware you have to call next()
Related
I was trying to make a routes for each ID I using a forEach loop but It stay loading until timeout reaches, all expected values are in place, all good but the second route is not running, I was fighting it despretly until now. I made sure there is a problem.
server.js
const router = require('express').Router();
function isAuthorized(req, res, next) {
if (req.user) {
next();
}
else {
res.redirect('/login')
}
}
let myguild = [];
router.get(`*`, isAuthorized, (req, res) => {
res.status(200);
console.log("wow");
console.log(req.user.guilds.length)
req.user.guilds.forEach(guild => {
myguild.push(guild);
})
console.log("Finished");
myguild.forEach(guild => {
console.log('Started')
router.get(guild.id, (req, res) => { // here is the problem
console.log("uh")
res.send("HAMBURGER")
console.log(req, res, guild)
})
console.log("Outed")
})
});
module.exports = router;
output:
wow
23
Finished
Started
Outed
Started
Outed
Started
Outed
Star... 'there is more but this is enough'
It should behave and run within server/${guild.id} but got (failed) request
Any Ideas?
You might need to redesign the API to better fit what you're trying to accomplish. If you already know which guilds are available then you'd need to create those before the server is initialized.
Even if they come from a database or are dynamic, you can loop through the guild "options" and create endpoints then provide access to them only if the user is qualified.
const { guilds } = require('./config')
const guildHandler = (req, res) => {
// Assuming you're doing more here
res.send('Hamburger')
}
guilds.forEach(guild => router.get(`/guilds/${guildId}`, guildHandler)
Or if you are NOT doingg something different in the middleware for each guild then you could just have a single route for guild.
router.get('/guilds/:guildId, guildHandler)
Not really sure what you're trying to accomplish but checkout out the Express docs. They solve most use cases fairly easily.
https://expressjs.com/en/api.html#req
You never call res.end() from your outer res.get() handler, so the request never completes.
And, with respect, creating route handlers like that in a loop is a mistake. It will lead to real performance trouble when your app gets thousands of guilds.
You'll want to use just one route, with a named route parameter, something like this.
const createError = require('http-errors')
router.get(':guildid', isAuthorized, (req, res, next) => {
const guildid = req.params.guildid
if (req.user.guilds.includes(guild)) {
console.log("uh")
res.send("HAMBURGER").end()
console.log(req, res, guildid)
} else {
next(createError(404, guildId + ' not found'))
}
})
Thanks for everyone helped.
Inspired answer
Final Result:
server.js
router.get('/:guildid', isAuthorized, (req, res, next) => {
console.log('started')
const guildid = req.params.guildid
if (req.user.guilds.some(guild => guild.id === guildid)) {
console.log('uh')
res.send("HAMBURGER").end()
} else {
res.sendStatus(404);
}
})
I'm new to javascript, nodejs, and express, and confused of using next().
I want my code to move on to the next router with next(), but it seems to move on to the next then.
My code:
//validation
router.post('/requests', (req, res, next) => {
let {myData} = req.body
basicCheck(res, cluster, myData)
.then(() => {
if (myCheck()) {
next()
return // Doesn't need to do rest of the code. Just move on to the next router.post
}
...
return Promise.all(somePromises)
})
.then(() => {
...
return Promise.all(somePromises)
})
.then(() => {
if (someCheck() {
next()
} else {
res.status(400).send('message') // My code reaches here! even when myCheck() is true
}
})
.catch((err) => {
...
})
})
// where next() needs to be
router.post('/requests', (req, res) => {
...
})
When next() is outside the basicCheck, next() goes to the next router.post.
I don't get the concept of where next() indicates.
How can I correct this code while doing myCheck() inside basicCheck()?
With next() you move to the next middleware.
Exapmle:
You have a route like:
app.get("/", (req, res, next) => {
res.send("hello")
})
Instead of using an anonymous function you can declare an function and use it it like:
function firstMiddleware(req, res, next){
res.send("hello")
}
app.get("/", firstMiddleware);
What you can do is you can have multiple middlewares in your route like:
function firstMiddleware(req, res, next){
console.log("hy");
next()
}
function secondMiddleware(req,res,next) {
console.log("hello")
res.send("hello");
}
app.get("/", firstMiddleware, secondMiddleware);
As you can see. In my first middleware i use next(). This tells express.js to move to the next middleware in this case secondMiddleware
The middlewares gets executed from the left to right and with next() you tell them to move to the next until you are on the end.
Usually the last middleware is your API endpoint and you should not use next() otherwise you would "jump out" of your route and you would receive an error if you have defined an global error handler
Also sidenote: A bonus would be to seperate your routes and logic by creating an file called controller.js for example.
controller.js
function firstMiddleware(req, res, next){
console.log("hy");
next()
}
function secondMiddleware(req,res,next) {
console.log("hello")
res.send("hello");
}
module.exports = {
firstMiddleware,
secondMiddleware
}
Now you can import it:
const { firstMiddleware, secondMiddleware } = require("./controller.js");
app.get("/", firstMiddleware, secondMiddleware);
This makes your code easier to maintain as it grows
EDIT:
router.post("/requests", async (req, res, next) => {
let { myData } = req.body;
let checkresult = await awbasicCheck(res, cluster, myData);
if (myCheck()) {
return next();
}
let someResults = await Promise.all(somePromises);
let someMoreResults = await Promise.all(somePromises);
if (someCheck()) {
return next();
} else {
res.status(400).send("message"); // My code reaches here! even when myCheck() is true
}
});
You use return witch yes stops the function from execution BUT what you also do is an promise chaining.
I have written here an async / await approach
I want to keep routes separate from controller.
My route is:
'use strict';
module.exports = function(app) {
var controller = require('../controllers/controller');
app.route('/').get(controller.index);
};
And controller is:
exports.index = function() {
request = new Request(
"MYQUERY",
function(err, rowCount) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
connection.close();
}
);
request.on('row', function(columns) {
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
console.log(column.value);
}
});
});
connection.execSql(request);
};
I am able to see the result in the terminal console but I want to return it as JSON to http. I can use the following if I am using controller and routes all together:
router.get('/about', function (req, res) {
res.send('About this wiki');
})
The callback function to .get (or any router request handler) takes at least two arguments: request and response. You can see this with your example:
router.get('/about', function (req, res) {
res.send('About this wiki');
})
You could rewrite this to make the callback a named function rather than an anonymous function:
const aboutHandler = function (req, res) {
res.send('About this wiki');
});
router.get('/about', aboutHandler);
Your controller.index is the same kind of function, so it will take those two arguments. You just have to change your function to take them:
exports.index = function (req, res) {
This will give you access to res, and you can use it as you need to do send the response via res.send or res.json if you build a JSON object by accumulating the row results. You can use request.on('end' ... to know when the query has emitted all its results.
I might be misunderstanding your question, but do you mean res.json(...);?
We have a route & a middleware like this:
When we do them like this:
//middleware
router.use((req, res, next) => {
// check header or url parameters or post parameters for token
let token = req.body.token || req.query.token || req.headers['x-access-token'],
// verifies secret and checks exp
jwt.verify(token, config.secret, (err, decoded) => {
if (err) {
return res.json({
success: false,
message: 'Failed to authenticate token.'
});
} else {
// if everything is good, save to request for use in other routes
res.locals.test = "test";
req.somevariable = "variable1";
console.log("res.locals.test inside middleware ", JSON.stringify(res.locals.test));
console.log("req.somevariable inside middleware ", JSON.stringify(req.somevariable));
next();
}
});
next();
});
//TestRoute
router.get('/TestRoute', (req, res) => {
console.log("res.locals.test outside middleware ", JSON.stringify(res.locals.test));
console.log("req.somevariable outside middleware ", JSON.stringify(req.somevariable));
});
The values of req.somevariable and res.locals.test are undefined outside middleware
When we do them like this:
//middleware
router.use((req, res, next) => {
res.locals.test = "test";
req.somevariable = "variable1";
console.log("res.locals.test inside middleware ", JSON.stringify(res.locals.test));
console.log("req.somevariable inside middleware ", JSON.stringify(req.somevariable));
next();
});
//TestRoute
router.get('/TestRoute', (req, res) => {
console.log("res.locals.test outside middleware ", JSON.stringify(res.locals.test));
console.log("req.somevariable outside middleware ", JSON.stringify(req.somevariable));
});
The values of req.somevariable and res.locals.test are available outside middleware.
What is the problem here?
res.locals.VARIABLENAME = req.user
VARIABLENAME (whatever variable you set it to) can show up as undefined when you use .ejs or when dynamic rendering with that variable, you can get errors like your variable name is undefined.
THIS IS AN ODDITY with res.locals: when you want to use the variable name you set to res.locals with rendering, you have to define req.user in your function THAT RENDERS THE FILE!
Backend: res.locals.currentUser = req.user
//THIS FUNCTION WILL RENDER PERFECTLY LETTING ME USE currentUser in my .ejs file
upgradeForm(req, res, next) {
let saved = req.user;
if(req.user){
res.render("users/upgrade");
} else{
req.flash("notice", "You've successfully signed in!");
res.redirect("/");
}
}
HOWEVER
//THIS FUNCTION WILL SAY currentUser is UNDEFINED IN MY .ejs file
upgradeForm(req, res, next) {
if(req.user){
res.render("users/upgrade");
} else{
req.flash("notice", "You've successfully signed in!");
res.redirect("/");
}
}
No code difference except for that the working function rendering has req.user set to a variable (you don't even have to use that variable). Took me 9 hours to solve this problem but now you know!
I am using Express.js as http server. Defined all my routes.
Most endpoints need to verify session before returning a response. E.g. below code serves users in the system and list of services respectively:
function getUsers(req, res, next) {
verifyUser(req, res, next, function () {
//serve users
});
}
function getServices(req, res, next) {
verifyUser(req, res, next, function () {
//serve services
});
}
You probably noticed there is a verifyUser function which validates the session. Which is as below.
function verifyUser(req, res, next, callback) {
var sessionKey = req.cookies.sessionKey;
var user = users.userBySession(sessionKey);
if (user) {
callback(req, res, next, user);
} else {
res.status(401).send({
message: 'Unauthorized'
});
}
}
As you can see I keep passing in req, res and next parameters along with a callback whenever I use this function.
I tried to use apply function to make it easier. Changed my getUsers function like this:
function getUsers(req, res, next) {
verifyUser
.apply(null, arguments, function () {
//serve users
});
}
The problem with this approach is callback is not passed into verifyUser function. And I don't really like passing null as scope with each call.
How can I achieve this by writing less and better code ? Any ideas?
You could use bind to create a 'partial function':
// create bound responseHelper object
var responseHelper = verifyUser.bind(null, req, res, next);
// usage
responseHelper(getUsersCallback); // same as verifyUser(req, res, next, getusersCallBack);
I think you're looking to turn verifyUser into a middleware function.
function verifyUser (req, res, next) {
var user = // yadda yadda session stuff
if (user) {
req.user = user; // [1] what you do to the req object here...
} else {
return res.status(401).send({ message: "No way Smokey Joe"});
/**
* alternatively, do something like
* var err = new Error("Not authorized");
* err.statusCode = 401;
* return next(err);
*
* this will kick off Express' error handling mechanism,
* which you should read about in the docs (see the link below)
*/
}
next();
// very important to call next after this verifyUser has done its job
// if you don't, the next middleware won't go off,
// and the request will just hang
}
function getUsers (req, res, next) {
// [2] will show up on the req object here, assuming you chain these
// two functions together as middleware
}
app.get("/users", verifyUser, getUsers);
app.get("/services", verifyUser, getServices);
// here's a route that needs no session auth, so no need to verifyUser
app.get("/latest-posts", getLatestPosts);
When you tell Express to use a function or attach a function to a route path via get('/my/route', hanlderFun) or some such, you've basically turned handlerFun into a middleware.
You can define however many middleware as handlers on a route as you like, and they'll all execute in turn as long as you keep calling next.
app.post("/checkout", verifyUser, tallyCart, checkInventory, doPayment, sendInvoice);
The job of next is to pass control from the current middelware to the next one. It's an object
You can do other stuff with next, too, which you should read up on in the docs.
http://expressjs.com/en/guide/writing-middleware.html
http://expressjs.com/en/guide/using-middleware.html
The docs on routing have good info on middleware as well:
http://expressjs.com/en/guide/routing.html
For extra credit, check out error handling middleware, too:
http://expressjs.com/en/guide/error-handling.html