I'm trying to make a query with template literals, like this:
router.post('/login', middleware.isLoggedOut, function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
else
{
console.log(req.body);
var y=0;
User.findOne({'username': req.body.username, `privileges.${y}.region`: req.body.regiuni}, function(err, usr)
{
if(err)
{
console.log(err);
}
else
{
if(usr === null)
{
console.log("no usr");
}
else
{
req.logIn(usr, function(err)
{
if(err)
{
console.log(err);
}
return res.redirect('/users/' + user.username);
})
}
}
})
}
})(req, res, next);
});
I can't really get how I should use the template literal here "privileges.${y}.region" because right now it doesn't work. I get "unexpected template string" in the node shell, but vs code also seem not to interpret it as I want because it colors the code like the template literal is this:
: req.body.regiuni}, function(err, usr)
{
if(err)
{
console.log(err);
}
else
{
if(usr === null)
{
console.log("no usr");
}
else
{
req.logIn(usr, function(err)
{
if(err)
{
console.log(err);
}
return res.redirect('/users/' + user.username);
})
}
}
})
}
})(req, res, next);
});
module.exports = router;
Why does it happen and how can I fix this?
You need to have it inside of brackets, like
[`privileges.${y}.region`]: req.body.regiuni
It's an object, think about the way you'd access it.
Would you do
obj.`privileges.${y}.region`?
Nop, you'd use brackets
obj.[`privileges.${y}.region`]
Related
The app is using basic Node.js, Express, and MongoDB to return some data at different routes.
Route:
router.get('/api/v1/:collection', (req, res, next) => {
try {
const data = ApiController.getAllRecipes(req, res, next);
console.log(data);
res.send(data);
} catch(error) {
res.send(error);
}
});
The methods that query the database are contained within a simple controller:
module.exports = {
getAllRecipes: async (req, res, next) => {
try {
req.app.db.collection(req.params.collection).find({}).toArray((error, result) => {
if (result.length > 0) {
console.log(result);
return result;
} else {
let error = new Error();
error.statusCode = 404;
error.message = 'No API results found.';
next(error);
}
});
} catch (error) {
next(error);
}
}
};
Inside the controller, the console.log(result); returns the correct data that I would like to be handled within the route file. However, the console.log(data); in the Route file returns undefined, even within the try/catch block.
Am I missing something in passing the data from the controller back to the route? Thank you :)
Found a solution! Since the controller is asynchronous, it doesn't need to return data, but rather save it to res.locals and execute Express' next() method to continue with the route.
Updated Route:
router.get('/api/v:versionNumber/:collection', ApiController.getAllRecipes, (req, res, next) => {
res.send(res.locals.results);
});
Updated controller:
getAllRecipes: async (req, res, next) => {
try {
req.app.db.collection(req.params.collection).find({}).toArray((error, result) => {
if (result.length > 0) {
res.locals.results = result;
next();
} else {
let error = new Error();
error.statusCode = 404;
error.message = 'No API results found.';
next(error);
}
});
} catch (error) {
next(error);
}
}
I am using passport.js for my node app. In the Custom Callback section I found the following code(lets say it Code A):
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
My question is I am not able to understand passing (req, res, next) at the end. How the following code(lets say it Code B):
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
});
});
How Code B is different from Code A ?
If I simplify Code A then it will be like :
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(..){..})(req, res, next);
});
Further
passport.authenticate(..)(req, res, next);
which means expression like
function(..)(req,res, next)
My Question is more about understanding the syntax
function(..)(parameters)
authenticate() function is structured like this:
module.exports = function authenticate(passport, name, options, callback) {
// ...
return function authenticate(req, res, next) {
// ...
strategy.success = function(user, info) {
if (callback) {
return callback(null, user, info);
}
}
// ...
})
};
So it takes two series of parameters:
The first one (in your case 'local' and the callback function) is used to tell passport to authenticate you, and how to do it;
The second handles the function to control your app with req, res and next parameters.
Hope it helps you to understand!
I'm developing a simple rest API in Node.js, and it works middling.
This is my controller code:
...
exports.listById = function(id, callback) {
Course.findById(id, function(err, courses){
if(err){
callback({error: 'Not Found'});
}
else{
callback(courses);
}
});
}
And this is my route:
app.get('/courses/:id', function(req, res){
var id = req.params.id;
courseController.listById(id, function(resp){
res.status(200).json(resp);
});
});
This code works and show results of my collection in mongodb.
But the code below, doesn't show results with postman:
app.get('/courses/:id', function(req, res){
var id = req.params.id;
courseController.listById(id, function(err, resp){
if(err){
res.status(404).send(err);
}
else{
res.status(200).json(resp);
}
});
});
exports.listById = function(id, callback) {
Course.findById(id, function(err, courses){
if(err)
return callback(new Error('Not Found')); // You must return Error by standard
callback(null, courses); // You must set first argument (error) to null
});
}
...
// You can check that id is number
app.get('/courses/:id(\\d+)', function(req, res, next) {
var id = req.params.id;
courseController.listById(id, function(err, resp) {
if(err)
return next(err); // Pass error to error-handler (see link below)
res.status(200).json(resp);
});
Best practice for callback function is first argument as error and second as result.You should
exports.listById = function (id, callback) {
Course.findById(id, function (err, courses) {
if (err) {
callback(error);
}
else {
callback(null, courses);
}
});
}
while your route should look like this:
app.get('/courses/:id', function (req, res) {
var id = req.params.id;
courseController.listById(id, function (error, courses) {
if (error) return res.status(500) // internal server error
// if I remember correctly, sources is empty array if course not found
res.status(200).json(resp);
});
});
The error prevents my webpage from being rendered. As mentioned in the title, the error lies in styles.css, when I take this file out, I do not get any errors.
styles.css is included in a separate headers.ejs file which is added in all pages, but there is only one route for which the error is shown(/cats/new). I put up some some logs around my routes and it seems when I enter /cats/new/, I am automatically redirected to a new route (get /cats/:id). I am wondering if this is the cause of the error?
I have attached my routes and the full error message below:
routes:
var express = require('express');
var router = express.Router();
var User = require('../models/user.js');
var Cat = require('../models/cat.js');
var Comment = require('../models/comment.js');
//middleware
function isAuthenticated(req,res,next) {
req.isAuthenticated() ? next() : res.redirect('/login');
}
router.get("/", function(req,res) {
res.redirect("cats");
});
router.get('/cats', function(req,res) {
Cat.find({}, function(err, cats) {
if (err) {
console.log(err);
} else {
res.render('cats', {cats: cats});
}
});
});
router.get('/cats/new', isAuthenticated, function(req,res) {
console.log('went to /cats/new');
res.render('new', {user: req.user});
});
router.post('/cats', isAuthenticated, function(req,res) {
console.log('went to post /cats');
var name = req.body.name;
var image = req.body.url;
var owner = req.user.username
var description = req.body.description;
cat = new Cat({
name: name,
image: image,
owner: owner,
description: description
});
cat.save();
User.findById(req.user._id, function(err, user) {
if (err) {
console.log(err);
} else {
user.cats.push(cat);
user.save();
}
})
res.redirect('cats');
});
router.get('/cats/:id', function(req,res) {
var id = req.params.id;
Cat.findById(id).populate('comments').exec(function(err, cat) {
if (err) {
console.log('entering get /cats/:id');
console.log(err);
} else {
console.log('no errror yet');
console.log(cat.comments);
res.render('show', {cat:cat});
}
});
});
router.post('/cats/:id', isAuthenticated, function(req,res) {
console.log(isAuthenticated);
var id = req.params.id;
Cat.findById(id, function(err, cat) {
console.log('findById running');
if (err) {
console.log(err);
console.log('err finding cat');
res.redirect('/cats');
} else {
console.log('before Comment.create');
Comment.create(req.body.comment, function(err, comment) {
console.log('after Comment.create');
if (err) {
console.log(err);
} else {
console.log('right after 2nd else');
comment.author.id = req.user._id;
console.log(req.user._id);
console.log(req.user.username);
comment.author.username = req.user.username;
comment.cat = id;
comment.save();
console.log('after saving comment');
cat.comments.push(comment);
cat.save();
console.log('saved cat');
User.findById(req.user._id, function(err, user) {
if (err) {
console.log(err);
} else {
user.comments.push(comment);
user.save();
console.log('saved user');
}
});
console.log(comment);
res.redirect("/cats/" + cat._id);
}
});
}
});
});
router.get('/cats/:id/edit', function(req,res) {
var id = req.params.id;
Cat.findById(id, function(err, cat) {
if (err) {
console.log(err);
} else {
res.render('edit.ejs', {cat:cat});
}
});
});
router.put('/cats/:id', function(req,res) {
console.log('beginning /cat/:id');
Cat.findByIdAndUpdate(
req.params.id, req.body.cat, function(err, updatedCat) {
if (err) {
console.log(err);
} else {
console.log('------------ req.body.cat');
console.log(req.body.cat);
console.log('------------ updated cat');
console.log('updated cat');
res.redirect('/cat/' + req.params.id);
console.log('not redirecting?');
}
});
router.delete('/cats/:id',isAuthenticated, function(req,res) {
var id = req.params.id;
console.log('YOU ARE TRYING TO DESTROY A CAT!');
Cat.findByIdAndRemove(id, function(err) {
if (err) {
console.log(err);
res.redirect('/user');
} else {
res.redirect('/user');
}
});
})
});
module.exports = router;
Error:
entering get /cats/:id
{ [CastError: Cast to ObjectId failed for value "styles.css" at path "_id"]
message: 'Cast to ObjectId failed for value "styles.css" at path "_id"',
name: 'CastError',
kind: 'ObjectId',
value: 'styles.css',
path: '_id',
reason: undefined }
It seems you’re including styles.css using a relative path in your template.
So when you navigate to /cats/:id, it tries to load /cats/styles.css.
In order to avoid that, you have to use an absolute path (e.g.: /styles.css or /public/styles.css – I’d recommend serving static files from a dedicated base path).
Go to
<head>
and change
<link rel="stylesheet" href="style.css">
to
<link rel="stylesheet" href="/style.css">
I'm quite new to both javascript and Node/Express, and it's probably a newbie question, but here goes...
I'm building a Rest API, and want to throw new Error(err.message) from this function:
function hentForfatter(id, callback) {
sql.connect(config, function(err) {
if(err) {
console.log(err);
callback(err);
}
new sql.Request().query('SELECT * from Forfatter where ForfatterID = ' + id).then(function(recordset) {
callback(recordset[0]);
})
.catch(function(err) {
console.log(err);
callback(err);
});
});
}
... so I can do this in my Express API route:
router.get('/:forfatterid/quizer/:quiz_id', function(req, res, next) {
try {
db.hentQuiz(1, function(result) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(result));
});
}
catch (error) {
res.status(404).send(error)
}
});
I can't get my head around how to do this... Anyone that can help? :)
In node, there is a convention that the first parameter of a callback should be the potential error.
function hentForfatter(id, callback) {
sql.connect(config, function(err) {
if(err) {
console.log(err);
return callback(err); //notice the return statement
}
new sql.Request().query('SELECT * from Forfatter where ForfatterID = ' + id).then(function(recordset) {
callback(null, recordset[0]); //notice I send null for the error
})
.catch(function(err) {
console.log(err);
callback(err);
});
});
}
(I'm not sure how you get form db.hentQuiz to hentForfatter.)
router.get('/:forfatterid/quizer/:quiz_id', function(req, res, next) {
db.hentQuiz(1, function(err, result) {
if(err) return res.status(404).send(error);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(result));
});
});
Try using two parameters if using callbacks:
callback(err, result)
And then check for
err and result.
In addition look up how promise chains work.