How to pass request body object to other routes? - node.js

Anyone know the solution? When I console log the variable it shows undefined. I need to pass the req.body (name and email) element to second post route which is "/company" route. I have two forms and I want to pass the first form data to second form the "/company" route form. then the two form data will be stored in mongoDb. I tried everything but I got only undefined in second route the "/company" route
import express from "express";
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
//Assign the name and email to variable and sent to last route
const middleware = (req, res, next) => {
const { name, email } = req.body;
let nameNew = name;
let emailNew = email;
// add nameNew and emailNew to req object
// so that it can be access in other routes
req.nameNew = nameNew;
req.emailNew = emailNew;
// console.log(nameNew);
// console.log(emailNew);
next();
};
//Get name email from user input and sent it middleware
app.post("/", middleware, (req, res, next) => {
const { name, email } = req.body;
res.send("Home route");
});
//Get the name and email from middleware
app.post("/company", middleware, (req, res) => {
// console.log(nameNew);
// access req.body without middleware
// console.log(req.body);
// access req.body using middleware
console.log(req.nameNew);
console.log(req.emailNew);
res.send("Company route");
});
//Server running
app.listen(4000, () => {
console.log(`Server Started `);
});

When your request gets into your app.post("/") it sets the nameNew variable inside your middleware scope. You cannot access this variable in your other routes.
If you want to access variables shared from your middleware you can use res.locals : https://expressjs.com/en/api.html#res.locals
You can't pass data from route 1 to route 2 through middleware.
It passes through the middleware and sets the variables but on your res.send theses variable will disappear. These are just set for the "instance" of the incoming request and on res.send will be destroyed.
You would need to send back data to the front-end to pass it back to your API for route 2.
You can call functions from your route definition :
app.get('/getUserInfos', isLoggedIn, (req, res) => {
return getUserInfos(res);
});
This way you can process your data and save it however you want.
Also, looks like you can chain functions there : https://stackoverflow.com/a/62723674/12343548

I use req.app.locals to send the data in first route to second route. Anyone want to do this type of program in future Here is the solution.
const express = require("express");
const app = express();
const path = require("path");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const middleware = (req, res, next) => {
const { name, email } = req.body;
req.app.locals.nameNew = name;
req.app.locals.emailNew = email;
next();
};
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname + "/index.html"));
});
app.post("/", middleware, (req, res) => {
const { name, email } = req.body;
res.send("Home Route");
});
app.get("/company", (req, res) => {
res.sendFile(path.join(__dirname + "/company.html"));
console.log(req.app.locals.nameNew);
console.log(req.app.locals.emailNew);
});
app.post("/company", (req, res) => {
console.log(req.app.locals.nameNew);
console.log(req.app.locals.emailNew);
res.send("Company Route");
});
//Server running
app.listen(4001, () => {
console.log(`Server Started `);
});

Related

In Node/Express, how to fetch the current route handler?

How do I fetch the syntax/name of the current route handler, ignoring the current specific param values?
e.g.:
app.get('/users/:id', (req, res) => {
let route = ?
console.log(route) // --> "/users/:id"
})
(Question 2 - can I do this in a middleware function?)
The correct answer is req.route.path
e.g.
1. Call directly from main file (app.js / index.js):
app.get('/admin/:foo/:bar/:baz', async (req, res) => {
console.log(req.originalUrl);
console.log(req.url);
console.log(req.path);
console.log(req.route.path); // this one is your answer
console.log(req.baseUrl);
console.log(req.hostname);
res.sendStatus(200);
});
API call:
http://localhost:3000/admin/a/b/c
Output
/admin/a/b/c (originalUrl)
/admin/a/b/c (url)
/admin/a/b/c (path)
/admin/:foo/:bar/:baz (route.path)
<nothing> (baseUrl)
localhost (hostname)
2. Call from a module:
app.js
const express = require('express');
const app = express();
...
const users = require('./users');
app.use('/api/users', users);
users.js
const express = require('express');
const router = express.Router();
...
router.get('/admin/:foo/:bar/:baz', async (req, res) => {
console.log(req.originalUrl);
console.log(req.url);
console.log(req.path);
console.log(req.route.path); // this one is your answer
console.log(req.baseUrl);
console.log(req.hostname);
res.sendStatus(200);
});
API call:
http://localhost:3000/api/users/admin/a/b/c
Output
/api/users/admin/a/b/c (originalUrl)
/admin/a/b/c (url)
/admin/a/b/c (path)
/admin/:foo/:bar/:baz (route.path)
/api/users (baseUrl)
localhost (hostname)
You can see below example for information about req object that you get.
/users can be obtained from req.baseUrl and :id can be obtained from req.params.id
app.use('/admin', function (req, res, next) { // GET 'http://www.example.com/admin/new?a=b'
console.dir(req.originalUrl) // '/admin/new?a=b' (WARNING: beware query string)
console.dir(req.baseUrl) // '/admin'
console.dir(req.path) // '/new'
console.dir(req.baseUrl + req.path) // '/admin/new' (full path without query string)
next()
})

Express: 4.17: Passing the variable to the next function returns undefined (middleware)

Issue
I am trying to pass my variable, req.app.locals.userId down to the /getuser route. Now I have tried with and without app in req.app.locals.userId. The issue is the variable keeps returning undefined in my /getuser route. I have tried to run the middleware directly in the router and the variable returns correctly, but it seems like req.app.locals does not work when I am using it as a middleware. req.app.locals returns an Object which means that req.app.locals works.
const verifyJWT = (req, res, next) => {
const token = req.headers["x-access-token"]
if (!token) {
res.send("We need a token")
} else {
jwt.verify(JSON.parse(token), "jwtSecret", (err, decoded) => {
if (err) {
res.json({ auth: false, message: "You failed to authenticate" })
} else {
req.app.locals.userId = decoded.id; //This is the variable I am trying to get
next();
}
})
}
}
router.route("/getuser", verifyJWT).get((req, res) => {
console.log(req.app.locals.userId) // <--- Returns undefined
});
I just can't see what I am doing wrong.
My index file
const express = require('express');
const cors = require('cors');
const jwt = require('jsonwebtoken');
const bp = require('body-parser');
const auth = require("./routes/auth");
const PORT = process.env.PORT || 3003;
const app = express();
app.use(cors());
app.use(express.json());
app.use("/auth", auth);
app.get("/", (req, res) => {
console.log("/");
});
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
Index file and your controller appear fine once working on your route file.
router.route("/getuser", verifyJWT).get((req, res) => {
console.log(req.app.locals.userId) // <--- Returns undefined
});
Instead of this try to get req...
router.get("/getuser", verifyJWT, (req, res, next) => {
console.log(req.app.locals.userId);
});
router.route() only takes one argument (the path to match).
Instead, use something like this:
router.route('/getuser').use(verifyJWT);
Or the mostly equivalent:
router.use('/getuser', verifyJWT);

How to call app.get() after app.use() node js express? Pass request from app.use() to app.get()

const express = require('express');
const app = express();
app.use('/', (req, res,next) => {
res.send('Bid Request GET');
});
app.get('/', (req, res) => {
res.send('Bid T');
});
app.listen(3000, () => console.log('app listening on port 3000!'))
I am beginner in node js. When I run the code it only shows app.use() response not app.get() response.
I am confused. i tried next() method also, but not working. how to solve this?
Main reason behind this is because you've already sent the response here:
app.use('/', (req, res,next) => {
res.send('Bid Request GET');
});
You can only send one response per request.
Each app.use middleware is a function with access to request, response, next parameter. when next function is invoked, it executes the middleware succeeding the current middleware.
You can also pass data from one middleware to another by creating variable in request or response. For Ex.
app.use('/', (req, res, next) => {
if(req.body.token !== 'abc') return res.sendStatus(503)
let someData = () => { .... SomeFunctionCode ... }
req.myVarible = someData // or res.myVariable = someData or anything
next()
})
But the recommended way of passing value is through res.locals.myVariable
Here is full example:
app.use('/', (req, res, next) => {
if(req.body.token !== 'abc') return res.sendStatus(503)
let someData = () => { .... SomeFunctionCode ... }
req.locals.myVarible = someData
next()
})
app.get('/', (req, res) => {
res.send(res.locals.myVariable)
})

Protect express.js endpoint with passport

I would like to protect some endpoints in my express app, I want to create something simple to manage if my app became a big app...now I'm doing something like this:
setProtected(router) {
const self = this;
router.use(this.auth);
...
}
setPublic(router) {
const self = this;
...
}
getRouter() {
const router = express.Router();
this.setPublic(router);
this.setProtected(router);
return router;
}
with:
auth(req, res, next) {
if(req.isAuthenticated()) {
console.log('req.isAuthenticated()', req.isAuthenticated());
return next();
}
return res.send(401);
}
the problem in this case is that is difficult maintain and it doesn't work well as if I have /:id in my publicRoute and for example /my-items in my protected route when I'm not logged and I try to reach /my-items I get the code of /:id.
Another idea was to create a json with the list of all my urls with same information like protected/not protected and eventual roles and then change auth with something like:
import urls from './urls';
auth(req, res, next) {
if (urls[req.url] == 'public') {
return next()
}
else if (urls[req.url] == 'protected' && req.isAuthenticated()) {
return next();
}
return res.send(401);
}
whats the best way for you?
You can chain middlewares:
eg.
const authenticate = (req, res, next) {
.. some auth logic
next();
}
app.use('/', main...
app.use('/profile', authenticate, otherMiddleware,
app.use('/admin', authenticate, isAdmin, otherMiddleware...
in your main file (server.js) import the routes and use the middleware there :)
server.js
const express = require('express')
const cors = require('cors')
const app = express()
// import admin routes
const adminRoute = require('./app/routes/admin.route.js')
// Add middleware for parsing URL encoded bodies (which are usually sent by browser)
app.use(cors())
// Add middleware for parsing JSON and urlencoded data and populating `req.body`
app.use(express.urlencoded({ extended: false }))
app.use(express.json())
// homepage route
app.get("/", (req, res) => {
res.json({ message: "Hello World" })
})
// restricted by middleware "isAdmin"
app.use('/api/v1', isAdmin, adminRoute)
app.listen(8008).on('listening', () => {
console.log('Server is running on 8008')
})
admin.route.js
const express = require('express')
const admin = require('../controllers/admin.controller.js')
const router = express.Router()
// get all admin users
router.get('/users', (req, res, next) => {
admin.getAdminUsers(req, res, next)
})
module.exports = router

Express dynamic include route based on user type

Need some help or any clue including/requiring dynamic routes at runtime in express, its confusing but i try my best.
This is just an example of app routes configuration right now
app.use('/', require('./routes/public'));
app.use('/u', require('./routes/user'));
app.use('/a', require('./routes/admin'));
for example require('./routes/public') will include something like this
router.get('/', home.index);
router.get('/faq', faq.index)
also require('./routes/user') will include this
router.get('/dashboard', user_home.index);
router.get('/accounts', user_acc.index)
also require('./routes/admin')
router.get('/dashboard', adm_home.index);
router.get('/accounts', adm_acc.index)
i have installed passportjs so its easy to check if the user is authenticated, also if it is, user contains 1 property type, eg: 1 = user, 2 = admin.
req.user.type = 1 or 2, req.isAuthenticated()...
what i need is inject depending user type 1 or 2, require('./routes/user') or require('./routes/admin') at runetime, cos i dont want to declare invalid routes for an user type user example including admin, or backwards.
Right now, all routes are visible or valid but i need to check every controller for user type, also i dont want the '/a' OR '/u' routes prefix.
All routes must be under '/'.
Request runs to first matched path. You can render page, throw error or call next to get next middleware. Below some router examples.
'use strict'
var express = require ('express');
var app = express();
var publicRouter = express.Router();
publicRouter.get('/', (req, res) => res.send('ROOT'));
publicRouter.get('/account', function (req, res, next) {
if (!is-user)
res.send('Hello guest')
else
next();
});
var userRouter = express.Router();
function isUser (req, res, next) {
// return next() on user logon, and error otherwise
return next();
}
userRouter.use(isUser);
userRouter.get('/dashboard', (req, res) => res.send('/dashboard'));
userRouter.get('/account', (req, res) => res.send('Hello user'));
var adminRouter = express.Router();
function isAdmin (req, res, next) {
// return next() on admin logon, and error otherwise
return next(new Error('Access denied'));
}
adminRouter.get('/manage', (req, res) => res.send('/manage'));
app.use(publicRouter);
app.use(userRouter);
app.use('/admin', isAdmin, adminRouter); // "/admin/manage", not "/manage"
// error handler
app.use(function (err, req, res, next) {
res.send(err.message);
});
app.listen(2000, () => console.log('Listening on port 2000'));
Another way is
app.get('/', do-smth);
app.get('/dashboard', isUser, do-smth);
app.get('/manage', isAdmin, do-smth);

Resources