How can I retrieve values from the uri in express js? - node.js

Hello I want to retrieve a value from the uri and use it in my code, for example what would you do if you had something like http://mysite.com/uri1/uri2 and you wanted to get only uri2 ?

app.get("/:uri/:id", function(req, res) {
var uri = req.params.uri,
id = req.params.id;
// do code
});
To clarify :uri and :id are named url segments.
The following with also work
app.get("/rooms/:roomId", function(req, res) {
Rooms.get(req.params.roomId, function(err, rooms) {
res.render("rooms/index", { rooms: rooms });
});
});

Related

How to use variables from app.post in order to find and match them to database in app.get?

Hey I'm trying to use variables from my app.post in app.get but I'm getting an error that variables are not defined.
basically, I'm receiving data from API calls (when the user is submitting an input in a form),
then filtering the data to relevant data I want to display and store this data in the mongoose database.
now the problem is when I'm trying to find data in app.get from my DB and equal it to the variables from the app.post (in order to render the data on a relevant page [using ejs]) then I'm getting the error >>> asin is not define
what am I missing here? please see my code below
app.get("/", function(req, res) {
Asin.findOne({asinId:asin},function(err){
if(!err){
res.render("home");
}
});
});
app.post("/", function(req, res) {
//SOME API LOGIC//
https.get(url,options,function(response) {
//DATA RCIEVED//
response.on("end",function(){
const asinData = JSON.parse(data);
const asin = asinData.products[0].asin;
const parentAsin = asinData.products[0].parentAsin;
const category = asinData.products[0].categoryTree[1].name;
const subCategory = asinData.products[0].categoryTree[0].name;
const fbaFee = asinData.products[0].fbaFees.pickAndPackFee/100;
const newAsin = new Asin({
asinId:asin,
parentAsinId:parentAsin,
categoryId:category,
subCategoryId:subCategory,
feesId:fbaFee
});
newAsin.save(function(err){
if(!err){
res.redirect("/");
}else{
console.log(err);
}
});
Well, all I had to do is create an empty var for each const before the app.get, that way I could use the variable in both routs.

I'm trying to create a global variable in express (also using mongoose), but the app keeps deleting the variable when the page is refreshed

I'm working on an e-commerce project. I'm trying to create a shopping cart within the app so that people don't accidentally access another user's data in the Mongo database. To do this, I tried setting up a variable as res.locals.cart. This didn't work because I found out from the docs that res.locals expires in each new page.
My next idea was to create an anonymous shopping cart each time app.js started and store it in the global app.locals object. This does work, and in the following code, you can see it returns the model of the shopping cart. But after that, it's undefined as soon as I refresh or go to a new page as seen by console.log. Why is it doing that? How can I make it so that my data stays across the whole app? And I need it to be a variable, so that it changes for each new user. If there are also any NPM packages that solve this problem, that would be helpful to know.
app.locals.cart = Cart.create({}, function (err, newCart) {
if (!err) {
console.log(newCart);
return newCart
}
});
app.get('/cart', function (req, res) {
console.log(app.locals.cart);
res.render('cart')
});
💡 This is not the best practive, but, if you still want to do it, than this is an example code you can see:
const express = require('express');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.locals.cart = [];
const item = {
id: 1,
name: 'Testing'
}
const addToCart = function(req, res, next) {
const { username } = req.body;
// req.body.username just for identifier
// you can change it with user id from token or token or whatever you want
if(typeof app.locals.cart[username] === 'undefined') {
app.locals.cart[username] = [];
}
// add item to cart by username / identifier
app.locals.cart[username].push(item);
next();
}
// or if you want to use this add to global, than you can use this middleware
// and now, you can see
// app.use(addToCart);
app.post('/', addToCart, (req, res, next) => {
// console.log
const { username } = req.body;
console.log(app.locals.cart[username])
res.send(app.locals.cart[username]);
})
app.get('/:username', (req, res, next) => {
const { username } = req.params;
console.log(app.locals.cart[username]);
res.send(app.locals.cart[username]);
})
app.listen(3000, () => {
console.log('Server is up');
})
I hope it's can help you 🙏.
I think the way you are trying is not a best practice.
Instead of using the locals try a different approach.
Creating a cart for each user in the database will be better.
You can link the card with the user. And whenever a user makes a request you fetch the cart from DB and do whatever you want.
To do that, you can add a user property to the Cart Schema. Whenever a user signs up, create a cart for it in the DB. When the user checkouts the cart, save the products in the card as another Document, let say an Order in the Orders Collection and clear the cart for future usage.
QUICK DIGEST:
Store any data from Mongoose onto a variable on your middleware and then have that variable read by app.locals or res.locals. The reason for this is because app.locals is changing and your middleware variable isn't, which lets it be read the same way every time. Example:
res.locals.data = middleware.var;
//or
app.locals.data = middleware.var;
Model.findById("model-id", function (err, noErr) {
if (!err) {
middleware.var = noErr //data retrieved from callback being passed into middleware.var
}
});
Here's what I discovered. My code didn't work because Express refuses to store data directly from a Mongoose function. I discovered this by console.logging the data inside the function and again outside it. I'm not sure why Express refuses to take data this way, but that's what was happening.
Cart.create({}, function (err, newCart) {
if (!err) {
app.locals.cart = newCart;
console.log(app.locals.cart);
//Returns Mongoose model
}
});
console.log(app.locals.cart);
//Now returns undefined
I solved this by storing the value to a variable in my middleware object called mids.
Here's the code on my app.js:
mids.anonymousCart();
app.use(function (req, res, next) {
res.locals.userTrue = req.user;
res.locals.cart = mids.cart;
next();
});
And here's the code on my middleware file:
var mids = {
anonymous_id: undefined,
cart: []
};
mids.anonymousCart = function () {
if (typeof mids.anonymous_id === 'undefined') {
Cart.create({}, function (err, newCart) {
if (!err) {
mids.anonymous_id = newCart._id.toString();
Cart.findById(mids.anonymous_id).populate('items').exec(function (err, cartReady) {
if (!err) {
mids.cart = cartReady;
}
});
}
});
}
}
What's happening here is that when app.js first starts, my middleware mids.anonymousCart is run. In my middleware, it checks that the id of Cart model stored as anonymous_id exists or not. It doesn't, so it creates the cart and stores the id. Since this is stored in the middleware and not Express, it can be accessed by any file linked to it.
I then turned the id I got back into a string, so that it could be read in the next function's findById. And if there's any items in the cart, Mongoose will then fill them in using the populate() method. But THE THING TO PAY ATTENTION TO is the way the data received in cartReady is stored in the middleware variable mids.cart, which is then read by res.locals.cart on app.js.

LinkedIn get people by Id in node.js

I want to get some data from an API of LinkedIn with Node.js.
I followed this tutorial https://www.npmjs.com/package/node-linkedin and I wrote this program that is suposed to send data to the console in the callback.
var Linkedin = require('node-linkedin')('XXX', 'XXX', 'http://localhost:3000/oauth/linkedin/callback');
var express = require('express');
var app = express()
// Initialize
var scope = ['r_basicprofile', 'r_emailaddress'];
var linkedinVariables = {
'accessToken': null,
'client': null
}
app.get('/oauth/linkedin', function(req, res) {
// This will ask for permisssions etc and redirect to callback url.
Linkedin.auth.authorize(res, scope);
});
app.get('/oauth/linkedin/callback', function(req, res) {
Linkedin.auth.getAccessToken(res, req.query.code, req.query.state, function(err, results) {
if (err)
return console.error(err);
console.log(results);
linkedinVariables.accessToken = results.access_token;
console.log("ACCESS TOKEN IS ", linkedinVariables.accessToken);
linkedinVariables.client = Linkedin.init(linkedinVariables.accessToken);
/* linkedinVariables.client.people.me(function(err, $in) {
console.log($in);
});*/
/*linkedinVariables.client.people.me('linkedin_id', ['id', 'first-name', 'last-name'], function(err, $in) {
// Loads the profile by id.
console.log($in);
});*/
linkedinVariables.client.people.id('HM3nX8nJD6', function(err, $in) {
console.log($in)
});
// return res.redirect('/');
});
});
app.listen(3000);
Now this program works fine and I get the data with this line:
linkedinVariables.client.people.me('linkedin_id', ['id', 'first-name', 'last-name'], function(err, $in) {
// Loads the profile by id.
console.log($in);
});
which get me a JSON response in my console but following the tutorial I'm suposed to get other informations about companies and people by ID but the response is blank even when I put my own ID to get my own information.
Is there something wrong with my code or is LinkedIn refusing all get requests?
use this
var scope = ['r_basicprofile', 'r_fullprofile', 'r_emailaddress', 'r_network', 'r_contactinfo', 'rw_nus', 'rw_groups', 'w_messages'];
insted of
var scope = ['r_basicprofile', 'r_emailaddress'];

Restrict Knex query on Bookshelf model to return only n records

I have the following code where I am using the splice function to pass only the first 10 /JSON objects to the JADE template.
app.get('/index', function(req, res) {
new models.Condos()
.query('orderBy', 'age', 'asc')
.fetch()
.then(function(names) {
var name = names.splice(0,10);
res.render('index', {
names: name.toJSON()
});
});
});
};
Is there any way where i could restrict the query itself to return only the first 10 records instead of splicing the array to do that (use the offset and limit parameters) ?
You can write a knex query to achieve this it will look something like:
app.get('/index', function(req, res) {
knex.select('*')
.from('condos')
.limit(10)
.then(function(names) {
res.render(names);
});
});
You will also need to require knex in your router file.
What I was looking for was something more along these lines.
app.get('/index', function(req, res) {
new models.Condos()
.query('orderBy', 'age', 'asc')
.query('limit','10')
.fetch()
.then(function(names) {
var name = names.splice(0,10);
res.render('index', {
names: name.toJSON()
});
});
});
};
You can use the Pagination plugin from Bookshelf.
models.Condos.fetchPage( {page:1, pageSize:10} )
Note: for the first page if the page size is 10, you can leave out the params and just
models.Condos.fetchPage()

How to validate multiple values at once and dose it need for MongoDB

I have the following express POST route handler that accepts GET and POST data something like this:
app.post('/handler/:id/:type', function (req, res, next) {
var id = req.param('id');
var type = req.param('type');
var body = req.body;
// Ho to check req.body params?
var document = _.extend(req.body, {id: id, type: type});
Collection.create(document, function (err, data) {
.....
})
});
Is it problem to don't check incoming parameters and write to MongoDB database as in example above? Or how can check this ones?

Resources