Node.js Express execute inside app.post() - javascript

I have a problem right now that I can't solve by myself. I assume you know more here. I'm just getting started.
By using the following code I'm getting a list of customers:
app.get("/customers", customers.findAll);
I wanted to add authentication. But now I don't know how to execute "customers.findAll" and get the value as JSON.
app.get("/customers", verifyToken, (req, res) => {
jwt.verify(req.token, 'justAtest, (err, authData) => {
if (err) {
res.sendStatus(403);
} else {
// execute customers.findAll
}
});
});
Customers is integrated via a requirement
const customers = require("../controllers/customer.controller.js");
The contents are as follows:
exports.findAll = (req, res) => {
Customer.getAll((err, data) => {
if (err)
res.status(500).send({
message:
err.message || "Some error occurred while retrieving customers."
});
else res.send(data);
});
};
Do you have any ideas?
Thank you in advance.
Grettings
Rok

You achieve that using something called "middleware". Explore it since it is very important.
Basically :
app.get("/customers", verifyToken,customers.findAll);
Wherre verify token is a funtion that has 3 parameters: req, res and 3rd one called "next".
So your verify token function would look something like:
(req, res,next) => {
jwt.verify(req.token, 'justAtest, (err, authData) => {
if (err) {
res.sendStatus(403);
} else {
next();
}
});
}
I took it from your snippet. Basically if you want to jump to customeeers.finalAll, just call "next" and it jumps to next function :D.

Related

How to get result by calling a routing not in app.js

In the file where I have written the request methods looks like this:
article.js
router
.route("/")
.all((req, res) => {
console.log("this should happen for any call to the article route");
})
.get((req, res) => {
// returns all the data in the database
Rest.find({}, (err, result) => {
if (!err) {
console.log(result);
res.send(result);
} else {
res.send(err);
}
});
})
.post((req, res) => {
const articleTitle = req.body.title;
const articleContent = req.body.content;
const articleDate = req.body.date;
const article = new Rest({
title: articleTitle,
content: articleContent,
date: articleDate,
});
article
.save()
.then((result) => {
res.send(result);
})
.catch((err) => {
res.send(err);
});
})
.delete((req, res) => {
Rest.deleteMany({}, (err, result) => {
if (!err) {
res.send(result);
} else {
res.send(err);
}
});
});
module.exports = router;
and I have and app.js
const article = require("./article");
app.use('/articles', article);
When I make a call to url it just loads and I get no response.
At first I was just writing it http verb on it own. But it was making my app.js have a lot of code so I decided to move all this logic to its own file article.js and use router.route() to chain the http verbs together to make the code look cleaner. But doing that I encounter the error when I get no result and it just loads forever.
Am I doing something wrong?
Any help is appreciated thanks.
I figured it out. The solution was to add next() to .all() method. Because I was passing next, I think the http request was just stuck at that point waiting.
So the new code should be
router
.route('/')
.all((req, res, next)) => {
// logic
next();
})
and the rest of the code follows.

Node.js error handling setup not working as intended

I am trying to have all my error messages in one file, each error is denoted by an error code, then in my functions/services, when there is an error, I call a function that takes the error code as an argument, then returns an object to the client with the error code and the respective error message from the errors.js file.
as an example, a user trying to register with an email that already exists in the database, here is how I try to do it:
// userService.js -- where my register function is
const { errorThrower } = require('../../utils/errorHandlers');
...
static async registerNewUser(body) {
const exists = await User.where({ email: body.email }).fetch();
if(exists) {
errorThrower('400_2');
}
...
}
errorHandlers.js file:
exports.errorThrower = (errCode) => {
throw Object.assign(new Error(errors[errorCode]), { errorCode })
}
exports.errorHandler = (err, req, res, next) => {
if(!err.status && err.errorCode) {
err.status = parseInt(err.errorCode.toString().substring(0, 3), 10);
}
let status, message
if (err.status) {
status = err.status
message = err.message
} else {
status = 500;
message = 'unexpected behavior, Kindly contact our support team!'
}
res.status(status).json({
errorCode: err.errorCode,
message
})
}
errors.js
module.exports = {
'400_1': 'JSON payload is not valid',
'400_2': 'user already registered',
...
}
...
const user = require('./routes/user');
const { errorHandler } = require('../utils/errors');
...
app.use('/user' , user);
app.use(errorHandler);
...
now with this setup, when hitting the register endpoint by postman, I only get the following in the console
UnhandledPromiseRejectionWarning: Error: user already registered
could someone please tell me what am I missing here?
thanks in advance!
You're not catching the error which you throw inside your errorThrower, thus getting the error UnhandledPromiseRejectionWarning. What you need to do is catch the error and pass it on the the next middleware, in order for the errorHandler-middleware to be able to actually handle the error. Something like this:
exports.register = async(req, res) => {
try {
await registerNewUser(req.body);
} catch(err) {
next(err);
}
};
If you don't want to do this for every middleware, you could create a "base"-middleware which handles this:
const middlewareExecutor = async (req, res, next, fn) => {
try {
return await fn.call(fn, req, res, next);
} catch (err) {
next(err);
}
};
Now you can pass your middlewares as an argument and delegate handling the error to the executor:
app.use('/user' , async (req, res, next) => middlewareExecutor(req, res, next, user));

Organize MongoDB request on Node.JS

I'm actually creating a chat like Discord with servers and channels using Node.JS, MongoDB and Mongoose.
Actually, my structure is this one:
https://github.com/copostic/My-Simple-Chat/tree/master/models
But to get the conversations, I have to make so much nested functions and I would like to know if there was a better way to organize my code..
Here's the code with the nested functions, I'm trying to get the message list of each channel of each server:
"use strict"
const Server = require('../models/server'),
Channel = require('../models/channel'),
Message = require('../models/message'),
User = require('../models/user');
exports.getChannels = function (req, res, next) {
// Only return one message from each conversation to display as snippet
Server.find({members: req.session._id})
.select('_id')
.exec(function (err, servers) {
if (err) {
res.send({ error: err });
return next(err);
}
servers.forEach(function (server) {
Channel.find({ serverId: server })
.exec(function (err, channels) {
// Set up empty array to hold conversations + most recent message
let fullConversations = [];
channels.forEach(function (channel) {
Message.find({
'channelId': channel._id
})
.sort('creationDate')
.limit(1)
.populate({
path: "author",
select: "profile.firstName profile.lastName"
});
.exec(function (err, message) {
if (err) {
res.send({
error: err
});
return next(err);
}
fullConversations.push(message);
if (fullConversations.length === conversations.length) {
return res.status(200).json({
conversations: fullConversations
});
}
});
});
});
});
});
};
Thanks a lot

Node.js - "TypeError - res.setHeader is not a function"

I'm trying to load JSON from a URL to a variable and send it back to the client's javascript
var getJSON =require('get-json');
app.post('/json', function(req, res) {
getJSON(url, function(err, res){
if(err)
{
console.log(err);
}
else
{
res.setHeader('content-type', 'application/json');
res.send(JSON.stringify({json: res.result}));
}
});
});
Every time I run the code the server says that res.setHeader isn't a function and the rest breaks.
Both post and getJSON callbacks have same res variable name.
Try this:
var getJSON =require('get-json');
app.post('/json', function(req, res) {
getJSON(url, function(err, response){
if(err)
{
console.log(err);
}
else
{
res.setHeader('content-type', 'application/json');
res.send(JSON.stringify({json: response.result}));
}
});
});
for me this was happening when fetching data in a forum i built. i found the fix to this in this blogpost:
https://dev.to/shailesh6363/facing-error-res-setheader-not-a-function-2oc9
i added code according to atul singh in the comments.
changes in app.js
app.use((res, next) => {
....
});
to
app.use((req, res, next) => {
....
});
now the app doesnt crash and it sucessfully fetches and displays the data

how to send back a post to a generated site

I'm trying to generate a page with the post connected to an id, I've got the id in to the node function witch I can see in the console but i don't know how i can render a new view with this posts content?
thankful for all ideas!
i think something is wrong with the search do to the fact that I don't get the item value in the console
in my node js file
router.param('id', function(req,res, next, id){
console.log(req.params.id)
db.collection('insights').find({_id:req.params.id}).toArray(function (err, items) {
res.json(items);
console.log(items)
});
res.send(items);
});
router.get('/share/:id', function(req, res) {
res.render('contact');
});
The param() callback is generally not for directly responding to requests (although maybe in case of error). It's to be used for loading data from databases, etc.
Here's what you might do:
router.param('id', function(req, res, next, id) {
db.collection('insights')
.find({_id: id})
.toArray(function(err, items) {
if (err) {
console.error(err);
return res.send(404);
}
req._items = items;
next();
});
});
router.get('/share/:id', function(req, res) {
res.render('contact', { items: req._items });
});

Categories