so i have a chat app that i am working on here and i am trying to make it to where a user can type in like https://niknet.ddns.net/room/randomroomUID and it will join them to that room if they are logged in (i use password for handling login and signup) my code looks like this on my routes.js (in case you dont know it's the js that handles all my express stuff)
i tried this
app.get('/room/:roomUid', isLoggedIn, function(req, res) {
console.log(req.params.roomUid)
console.log(req.user)
res.cookie('uid',req.user.uid, { maxAge: 999999999999999999999});
var username = req.user.displayName;
app.post( 'apolloMainchat',{ roomUid:req.params.roomUid , username});
});
but im not sure how to pass the information across to the express code that handles when users /apolloMainchat
typically a user can get to /apolloMainchat like this
app.get('/apolloMainchat', isLoggedIn, function(req, res) {
console.log(req.user)
res.cookie('uid',req.user.uid, { maxAge: 999999999999999999999});
var username = req.user.displayName;
res.render('apolloMainchat.ejs', username);
console.log(req.user.displayName)
});
any one know how to help me?
You will want to pass this by redirecting the client to a new endpoint and then reading those parameters from the query as Renato Gama said in the comments.
Your code will then become something like this.
app.get('/room/:roomUid', isLoggedIn, function(req, res) {
res.cookie('uid',req.user.uid, { maxAge: 999999999999999999999});
app.redirect('apolloMainchat?roomUid=' + req.params.roomUid);
});
app.get('/apolloMainchat', function(req, res, next) {
console.log(req.params.roomUid);
});
You're just using a HTTP redirect to pass them to the new endpoint and attaching the data as a query parameter as you would if they requested it directly. It's not quite clear what you're trying to achieve, but this should do what you've described.
Related
I have a post method to grab some data from a form. I then have to render another form which has a different post route. I want to use the variable I got from the first post method in the new post method.
I have a post method to grab the variable username
router.post('/', function(req, res, next) {
var username = req.body.username
res.render('add_user', {username: username})
});
Now I want to use it in a different post method:
router.post('/add_user', function(req, res) {
// I want to use the username variable here
})
Note: both the post methods are in the same file named index.js
Any help would be appreciated.
There are a few ways to accomplish this. First way would be for the second request to pass in the username.
But if you need to maintain a variable on the server and use it between requests, just put it outside of the handlers. Something like this:
let globalUsername= "";
router.post('/', function(req, res, next) {
var username = req.body.username;
globalUsername = username;
res.render('add_user', {username: username})
});
router.post('/add_user', function(req, res) {
res.send(globalUsername);
})
Not a very good solution though; unless you will have only 1 user hitting your website. If you have multiple users, then you need a way to identify them. Common ways include the client passing the username (or a token representing the user) on every request, or a cookie, etc. Look into sessions, cookies, JWTs, and other auth mechanisms.
But if you just want to share a variable across a couple of different requests, just put the variable on the global scope (or anywhere where both handlers can read it.)
I've found in quite a few SO posts that in order to rewrite a URL in Express 4 I would do something like the following:
router.use('/one/:someId', (req, res, next) => {
req.url = `/two/${req.params.someId}`;
next();
});
router.get('/one/:someId', (req, res) => {
res.send("reached /one/:someId");
});
router.get('/two/:someId', (req, res) => {
res.send("reached /two/:someId");
});
But when I try this, not only does the URL does not change to my expected "/two/some integer" and stays being "/one/some integer" but it gets to the 404 - Not Found page I have set up in my app file.
This routes are in a router file and I have also tried setting the URL to:
req.url = `/routerPath/two/${req.params.someId}`;
but the result is exactly the same.
So what could I be missing?
Thank you.
You have to distinguish two kinds of redirects:
Internal redirects work on the server, without the client noticing. They are a convenience for your server programming and never necessary - you could always introduce a helper method that gets called by all endpoints.
HTTP redirects advise the client (e.g. a web browser) to go to a different URL. Since you expect the URL to change, that's the one you want.
Simply call res.redirect, making sure to encode special characters:
router.get('/one/:someId', (req, res) => {
res.redirect(`/two/${encodeURIComponent(req.params.someId)}`);
});
router.get('/two/:someId', (req, res) => {
res.render("reached /two/:someId");
});
I am working with a single app application framework called reactjs, the issue I encountered is setting httpOnly cookies, as they can not be set / read from a client side I needed to figure out a way how to use express for this.
One idea I came up with is to make a post request to a route like /cookie:data where data is value of token that needs to be stored in a cookie, so:
app.post('/cookie:data', function(req, res) {
// Set cookie here
res.send(200)
})
Issue I am hesitant about is that token contains unique user identifier that is used to secure api, and I am not sure if I am or am not exposing this by setting up a cookie this way.
Alternatively instead of using :data it would be beneficial to figure out how I can grab data (json object) from the post request
EDIT:
One issue I can think of is that anyone can post to this route and set different cookies? what would be a way of securing it?
EDIT 2:
This is the express setup I use to proxy api calls (only relevant for clarifying comments)
app.use('/api', function (req, res) {
let url = config.API_HOST + req.url
req.pipe(request(url)).pipe(res)
})
Say that you want to proxy all requests starting with /api to a third-party, except /api/users, which you want to perform 'manually' because it returns a token you need:
app.post('/api/users', function(req, res) {
let url = config.API_HOST + req.url;
let apiRequest = request.post(url, function(err, response, body) {
// Responses are just examples, you should tailor them to your situation
if (err) {
return res.sendStatus(500);
} else if (response.statusCode !== 200) {
return res.sendStatus(response.statusCode);
} else {
res.cookie('token', body).send('OK');
}
});
req.pipe(apiRequest);
})
app.use('/api', function (req, res) {
let url = config.API_HOST + req.url
req.pipe(request(url)).pipe(res)
})
I am trying to simply set the cookie for the JSON Web Token during authentication in my Node.js and Express web application.
Since I cannot do res.redirect after using res.cookie(), how can I achieve this?
router.post('/', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (!user) { return res.redirect('/auth'); }
var theToken = jwt.encode({ id : user.id }, req.app.get('appSecret'));
res.cookie(theToken);
return res.redirect('/profile/' + username);
})(req, res, next);
});
Am I approaching this problem correctly? I cannot find much of anything on how people are setting their JSON Web Tokens once they have created them.
It seems that res.redirect works with setting the cookies, despite what some other SO answers state. Hopefully this helps someone else.
I have a Jade file that all of my templates extend called layout.jade. In it I want to be able to have a logout button if the user is currently logged in (this is kept track of in req.session).
So layout.jade will have something like,
-if (loggedin)
a.navButton(href="/logout") Log Out
The route for a page would look something like,
app.get("/foo", function(req, res) {
res.render("foo", {loggedin: req.session.isValidUser});
});
The thing is, I don't want to have to populate the loggedin variable manually in every single route. Is there a way I can use Express middleware to automatically set some default options for the object sent to res.render? Or is there a better method to do this?
Basically I'm asking how I can have some set of variables always sent to templates, as well as the ability to have certain custom variables available in certain templates by manually setting them in the routes.
It seems this is actually a documented feature I just had trouble finding, unless anyone has a better way of doing it; From the latest Express documentation,
app.locals: Application local variables are provided to all templates
rendered within the application. This is useful for providing helper
functions to templates, as well as app-level data.
So in my login success function has,
req.session.username = profile.username;
app.locals.username = profile.username;
My logout function,
app.get('/logout', function (req, res) {
delete app.locals.username;
req.session.destroy();
res.redirect('/login');
});
And finally in layout.jade/all of my templates,
- if(username)
a.navButton(href="/logout") Logout
If you set res.locals.loggedin in the /login route, as hexacyanide suggests, this local will not be available in the route for /foo. res.locals is cleared upon every request.
you could instead try placing this above other routes:
app.all('*', function(req, res, next){
if(req.user){
res.locals.loggedin = true;
res.locals.currentuser = req.user;
};
next();
});
Pretty sure that if you modify req.user during your route, the res.locals.currentuser that you set before won't updated to be the new req.user. but not certain about that.
I actually use a custom render function for each page where I render a template, it looks like this:
function myRender(templateName){
return function(req, res){
res.locals.currentuser = req.user || null;
res.render(templateName);
};
};
and I use it like this:
app.get('/foo'
, function(req, res, next){
res.locals.bar = req.query['bar'] || "";
console.log('passing request to myRender middleware');
next();
}
, myRender('foo-jade-template')
)
This has the advantage of only setting res.locals.currentuser when I am ready to render something, instead of before executing my route. So if I change req.user it is guranteed to have the most recent version at render time.
There is a line of code that is rather useful to you in the Express source:
// merge res.locals
options._locals = self.locals;
Therefore, when you run res.render(), Express will also take any locals that are stored in res.locals and pass them into the render. Therefore, all you have to do is set res.locals.loggedin to true, and then run res.render() as usual.
app.get('/login', function(res, res) {
res.locals.loggedin = true;
});
app.get('/foo', function(req, res) {
res.render('foo', {});
});