Error handling in node js backend - node.js

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

Related

Why is this express route returning a 200 status code when the code says to return a 500?

I have this route that is expcted to return a 500 status code.
/* Return all the users id */
router.post('/user/list', async function (req, res, next) {
const data = await scanAll(req.body.port, req.body.ip);
console.log("data ", data) //data 500
if (data === 500) {
res.json({
error: "Error, server connection refused"
}).status(500);
}
else if (data.length === 0) {
res.json(data).status(204)
} else {
res.json(data).status(200);
}
})
It scans a redis server and returns the data.
Well my front end received the json of the error. But receives the 200 status code. Same goes for postman
How is that possible?
According to Express API: https://expressjs.com/en/4x/api.html#res.status
You need to call status before calling json or send
res.status(400).send('Bad Request')
res.status(500).json({ error: "Error, server connection refused" })
Refer examples from,
https://expressjs.com/en/4x/api.html#res.send
https://expressjs.com/en/4x/api.html#res.json
https://expressjs.com/en/4x/api.html#res.status
So change the above snippet to,
/* Return all the users id */
router.post('/user/list', async function (req, res, next) {
const data = await scanAll(req.body.port, req.body.ip);
console.log("data ", data) //data 500
if (data === 500) {
res.status(500).json({
error: "Error, server connection refused"
});
}
else if (data.length === 0) {
res.status(204).json(data);
} else {
res.status(200).json(data);
}
})

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');
});
}
});
});

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.

Node.js Express - Conditional Rendering of Template

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);
});
});

404 Response not being set on error | Node.JS & MongoDB

I'm facing a issue in a Node.JS application I'm writing.
I'm trying to get a JSON string as POST and saving that JSON to mongodb.
Inserts are working fine but I'm not able to handle error scenarios from snippet which is responsible for interacting with mongodb.
E.g. in the snippet below, I'm getting expected 404 response at "Error" comments #1, 3, 4 in server.js, when respective conditions are fulfilled, but 404 response at comment #2 is not coming.
However, I am getting errors printed in console from insertintomongo.js at comment #5 and 6 and that error object is also successfully sent back to server.js.
I'm not able to figure out why response is not set to 404 even when I know that code has gone into correct if condition (as shown by console output).
Snippet of JS handling requests (server.js)
var imongo=require("./insertintomongo.js");
http.createServer(function (request, response) {
if (uri == "/ssd/add" && request.method == 'POST') {
console.log(request.method + " to " + request.url);
var fullBody = '';
request.on('data', function(chunk) {
fullBody += chunk.toString();
});
request.on('end', function() {
try {
JSON.parse(fullBody);
} catch (e) {
// Error 1
console.log('Invalid JSON. Error message: ' +e);
response.writeHead(404, "Input data is not in JSON format" , {'Content-Type': 'text/html'});
response.end('<html><head><title>Input data is not in JSON format</title></head><body><h1>Input data is not in JSON format</h1></body></html>');
}
var inputJSON = JSON.parse(fullBody);
if ( inputJSON.deployment_id != undefined ){
inputJSON._id=inputJSON.deployment_id;
imongo(inputJSON,function(err){
if(err){
// Error 2
console.log('Error 2: ' + err);
response.writeHead(404, "Error saving input data" , {'Content-Type': 'text/html'});
response.end('Error inside callback');
} else {
console.log("All good");
};
});
} else {
// Error 3
console.log("Incorrect json provided");
response.writeHead(404, "Incorrect json provided", {'Content-Type': 'text/html'});
response.end('<html><head><title>Incorrect json provided</title></head><body><h1>Incorrect json provided.</h1><h3>"deployment_id" field is missing.</h3></body></html>');
};
// OK 1
response.writeHead(200, "OK", {'Content-Type': 'text/html'});
response.end();
});
} else {
// Error 4
response.writeHead(405, "Method not supported", {'Content-Type': 'text/html'});
response.end('<html><head><title>Method not supported</title></head><body><h1>Method not supported.</h1></body></html>');
}
}).listen(8081);
insertintomongo.js which is included in above JS
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://localhost:27017/mytest';
function saveToMongo(input,cb){
MongoClient.connect(url, function (err, db) {
if (err) {
// Error 5
console.log('Unable to connect to the mongoDB server. Error:', err);
cb(err);
} else {
var collection = db.collection('users');
collection.insert([input], function (err, result) {
if (err) {
// Error 6
cb(err);
} else {
console.log('Inserted '+ result.result.ok+ ' documents into collection. The documents inserted with "_id" are:' + JSON.stringify(result.ops));
cb(null);
}
db.close();
});
}
});
};
module.exports=saveToMongo;
Here's Console output
Server runing at 8081
POST to /ssd/add
// This is coming from inserttomongo.js
Error 5: Unable to connect to the mongoDB server. Error: { [MongoError: connect ECONNREFUSED 127.0.0.1:27018]
name: 'MongoError',
message: 'connect ECONNREFUSED 127.0.0.1:27018' }
// This is coming from server.js
Error 2: MongoError: connect ECONNREFUSED 127.0.0.1:27018
OK, figured out the issue. I had to remove these lines from previous place and put it in else condition of "Error 2" comment.
// OK 1
response.writeHead(200, "OK", {'Content-Type': 'text/html'});
response.end();
This is because call to imongo is async and response was being set 200 even before the imongo was finished.
Very basic mistake :(

Resources