Node.js Express - Conditional Rendering of Template - node.js

I am using Express and Passwordless module to setup passwordless authentication. Everything works, gte, but i am stuck at one issue.
As a part of the delivery method, I am using an external api to send the sms to the user. If the sms is sent correctly, everything works fine. However, if the sms fails to send, there is still no error, but the response from the api call tells me that the sms wa a failure. In case of failure, the api response looks like this:
{ warnings: [ { message: 'Message sending has failed', numbers: '91545454' } ], errors: [ { code: 51, message: 'No valid numbers specified' } ],
status: 'failure' }
Now, in my node/express app, if the api response has status = failure, I would like to send them to a different page where I will tell users that the sms failed.
My code looks like this:
passwordless.addDelivery(
function(tokenToSend, uidToSend, recipient, callback) {
var smscall = 'MY API CALL URL;
needle.get(smscall, function(error, response) {
if(error) {
console.log(error);
}
if (!error && response.statusCode == 200) {
console.log(response.body);
}
if(response.body.status == 'failure') {
console.log('Failed');
THIS IS WHERE I WOULD LIKE TO REDIRECT USER TO A DIFFERENT TEMPLATE OR RENDER A MESSAGE.
}
callback(error);
});
});
The requestToken code looks like below:
router.post('/', passwordless.requestToken(function(user, delivery, callback) {
callback(null, user);
}, { failureRedirect: '/error' }),
function (req, res) {
res.render('verify', { uid: req.passwordless.uidToAuth });
}
);

Try to call a callback with error in your last condition block.
if(response.body.status === 'failure') {
console.log('Failed');
return callback(new Error(response.body.status));
}

Just call res.render where you check for the failed sms status :
passwordless.addDelivery(
function(tokenToSend, uidToSend, recipient, callback) {
var smscall = 'MY API CALL URL;
needle.get(smscall, function(error, response) {
if(error) {
console.log(error);
}
if (!error && response.statusCode == 200) {
console.log(response.body);
}
if(response.body.status == 'failure') {
console.log('Failed');
return res.render('smsFailPage');
}
callback(error);
});
});

Related

Making multiple requests to Spotify add to queue endpoint

I’m developing an application using Express and I need to call the Spotify endpoint to add to a user’s queue multiple times with different parameters, basically in a for loop. All requests return a 2xx status code, but not all of the tracks were actually added to my queue. It could be that only one was added, or multiple, but never all. I’m not really sure how to debug this because the call is returning a 2xx response code every time, so I’m wondering if perhaps there’s a general rule of thumb for making multiple calls to an API.
Here is where I call addToQueue in a loop:
let finishedRequests = 0
requests.forEach(async r => {
addToQueue(r.songId, accessToken, async () => {
try {
await RequestModel.findByIdAndUpdate(r._id, { $set: { serviced: true, accepted }})
return {
status: 200
}
} catch(err) {
return {
status: 500,
message: JSON.stringify(err)
}
}
})
.then(response => {
if (response.status === 500) {
return res.status(500).json({ err: err.message })
}
finishedRequests++
if (finishedRequests === requests.length) {
return res.status(200).send()
}
})
.catch(err => {
return res.status(err.status).json({ err: err.message})
})
And here is the addToQueue function:
const addToQueue = (songId, accessToken, successCallback) => {
return new Promise((resolve, reject) => {
const options = {
url: `https://api.spotify.com/v1/me/player/queue?uri=spotify:track:${songId}`,
headers: {
'Authorization': `Bearer ${accessToken}`
},
json: true
}
requestModule.post(options, async (error, response, body) => {
if (!error && response.statusCode >= 200 && response.statusCode < 300) {
resolve(successCallback())
} else {
if (error) {
reject({
status: 500,
mesage: JSON.stringify(error)
})
} else {
if (response.statusCode === 404) {
reject({
status: 404,
message: 'no queue'
})
}
reject({
status: response.statusCode,
message: 'spotify error'
})
}
}
})
})
}
Any help in making sure that all tracks are added to the queue is appreciated. Thanks
I was experiencing the same problem but solved it by making sure all requests are executed one after the other. You should try using a recursive function instead of the forEach. Once a request returns a positive status you would rerun the same function but only with the remaining songs as the parameter.
This way the requests will be added to the queue in the correct order and you won't add a bulk of songs in the same second. This also brings the benefit that you can be pretty sure that the songs will be in the right order when arriving in the Spotify queue.
I hope I could help!

send post respond in nodejs

I have used bcrypt to encrypt the password in my signup process..Here is my login code..I want to send a respond only if the password and email are correct.If the email is wrong it gives an alert- "fail"..If all are correct it gives an alert-"success".But In this code if password is wrong it doesn't send nothing and I cant use an alert for that..How can I send a respond with nothing to get that alert?
This is my reactjs code .....
fetch("http://localhost:3000/reg/getuser",
{
method:"POST",
headers: {
"Content-Type": "application/json"
},
body:JSON.stringify(user)
})
.then(function(response)
{
return response.json();
})
.then(function(data,props)
{
if(data.length == 0)
{
console.log("damn");
window.alert('Login Failed!')
}
else
{
console.log("done");
window.alert('Login Successful!');
}
});
This is my nodejs code...
router.post('/getuser',function(req,res)
{
Customer.find({email:req.body.email})
.then(function(details){
if(details.length<1)
{
res.send(details)
}
else
{
bcrypt.compare(req.body.password,details[0].password,(err,result)=>{
if(err){
console.log(err)
}
if(result){
res.send(details)
}
// here,when password is wrong...want to send a respond as
// data.length==0 (in fetch)
});
}
});
});
On a authentification you should work with a correct status code.
You can set your status-code with res.status(200).send('loggedin').
Use following status-codes:
200 - to say ok login was successful
400 or 401 - to say auth has failed.
To show the error message or to redirect the user check the status-code from your ajax request and do your stuff.
Edit fixed client snippet.
client
fetch("http://localhost:3000/reg/getuser",
{
method:"POST",
headers: {
"Content-Type": "application/json"
},
body:JSON.stringify(user)
})
.then(function(response)
{
if (response.status === 200) {
console.log("ok");
console.log(response.json());
window.alert('Login successfull!')
} else {
console.log("damn");
window.alert('Login Failed!')
}
})
.catch(function() {
console.log('error handling');
});
server
router.post('/getuser',function(req,res)
{
Customer.find({email:req.body.email})
.then(function(details){
if(details.length<1)
{
res.status(400).send(details)
}
else
{
bcrypt.compare(req.body.password,details[0].password,(err,result)=>{
if(err){
console.log(err)
}
if(result){
return res.status(200).send(details);
// return res.status(200).json(details); Use this line to send a json if result is an object.
}
return res.status(400).send('login failed');
});
}
});
});

NodeJS route with API request in it error

I am writing a route that checks if a system app is online and then responds to the client with a simple 200 status ok, or a 404 status.
I'm using express and request to make the api call.
Route looks like this:
app.get('/status/keymgr', async (req, res, next) => {
try{
var endpoint = `http://${config.KeyManager.host}:${config.KeyManager.adminPort}/healthcheck`;
console.log(endpoint);
await request.get(endpoint, function(err, response, body){
if (!err && response.statusCode == 200){
res.send('OK');
}else{
res.status(404);
}
}).end();
}catch(error){
res.status(404);
}finally{
next();
}
});
For some reason, I am getting the following error:
uncaughtException: Can't set headers after they are sent.
I am guessing some kind of response is being sent to the browser before the route runs the res.send() or the res.status().
I can't figure out what's wrong here. Any idea??
AS #ndugger mentioned, the reason you are getting this exception is because request.get does not return a promise and hence await here is of no use. You have two options, either you use util.promisify or wrap your request under a new promise and resolve only when the callback finishes. Something like this
app.get('/status/keymgr', async (req, res, next) => {
var endpoint = `http://${config.KeyManager.host}:${config.KeyManager.adminPort}/healthcheck`;
console.log(endpoint);
try {
await new Promise((resolve, reject) => {
request.get(endpoint, function (err, response, body) {
if (!err && response.statusCode == 200) {
// res.send('OK');
resolve('OK');
} else {
reject('404')
// res.status(404);
}
});
});
res.send('OK');
} catch (err) {
res.status(404);
} finally {
next();
}
}

Unexpected token in JSON argument in POST request

I am trying to make a POST request to a nodejs server from an Ionic application work, but I stumbled on this error.
Http failure response for http://127.0.0.1:3000/services/user/signin: 500 Internal Server Error", SyntaxError: Unexpected token u in JSON at position 0;
I have access to both the application and the API server. Task at hand, trying to send credentials to the server, which will check if those credentials are recognized and will send a response. The server side code works just fine, since I have a web app accessing to the same resources and working like a charm.
Here goes the code.
Home page:
doLogin() {
this.remoteService.login(this.user);
}
user is a key value array
user = { email:'', password:'' };
Now for the login function in the remoteService injectable:
login(user){
let headers = new HttpHeaders();
headers.append('Content-Type', 'application/json');
console.log(JSON.stringify(user));
this.http.post(serviceUrl+'/user/signin', JSON.stringify(user), {headers: headers}).subscribe(
function(response) { console.log("Success Response" + response)},
(err: HttpErrorResponse) => {
if (err.error instanceof Error) {
console.log(err);
} else {
console.log(err);
}
}
);
}
I used this line
console.log(JSON.stringify(user));
to test the function argument for JSON correctness, and it's a charm.
Finally, this is the nodejs server code
if(label === 'signin') {
return function (req, res, next) {
{
var user = JSON.parse(req.query.user);
db.query('SELECT username as id FROM user where email = ? and password = ?', [user.email,user.password], function (err, result) {
if (err) {
next(err);
}
else {
if(result.length === 1) {
delete user.password;
req.session.user = result[0];
req.result = 400;
}
else
{
req.result = 404;
}
next();
}
});
}
};
}
Could you please help me fix the nasty error? I have been banging my head on this all day long and a big part of the last night.

Error handling in node js backend

I'm using a node.js backend and I got some problems with the error handling.
In the backend I use express for routing. I get a ajax post from the frontend with a array and some data in it. This data should be saved in the database. If there is an error by adding the data to the DB I get the error message in the backend but I also want so send a message to the frontend. I was try and erroring around but in the frontend I always get 'succesfull'.
This is my code till now.
Backend:
router.post('/tagging', function(req, res) {
var taggedData = req.body;
var actions = taggedData.map(element => {
addTaggedData.addTaggedData(element)
.then(function(result) {
return result;
})
.catch(function(err) {
if (err.code == "ER_NO_SUCH_TABLE") {
console.log("Tagged data contains unknown project name");
res.send("ER_NO_SUCH_TABLE");
} else {
res.send(err);
}
})
});
Promise.all(actions)
.then(
res.send("Successful")
)
.catch(function(err) {
if (err.code == "ER_NO_SUCH_TABLE") {
console.log("Tagged data contains unknown project name");
res.send("ER_NO_SUCH_TABLE");
} else {
res.send(err);
}
});
})
Frontend ajax call:
function postTaggedData(taggedData) {
$.ajax({
url: server_connection.url + '/tagging',
type: 'POST',
encoding: "UTF-8",
contentType: 'application/json',
data: JSON.stringify(taggedData),
success: function(data) {
if (data === "Successful") {
console.log("Tagged Data successfully send to server");
}else if(data == "ER_NO_SUCH_TABLE"){
alert("Unknown project");
} else {
alert(data);
}
},
error: function(xhr, status, error) {
if(error == "Internal Server Error"){
alert("There is an error with the server");
}else if(error == "ER_NO_SUCH_TABLE"){
alert("Unknown project");
}else{
alert("There was an error while sending the Tagged Data to the server");
console.log(xhr, "Status: ", status, error);
}
}
})
}
Even though you're sending error as a response, express doesn't know it's an error, so it sends it with status code 200 which means OK, so front-end thinks, response was successful.
Try setting the non-ok status and then sending an error like this: res.status(404).send(err). Where 404 is a status code for "Not Found"
You can find more about status codes here
You can find more about express error handling here

Resources