send post respond in nodejs - node.js

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

Related

axios retry request but data-object isn't sent again

I have a react native app and a nodejs backend. I'm using refresh and access tokens for authentication. My RN code looks like this (simplified):
const onRequest = (config) => {
console.log('data before request', config.data);
config.headers = {
'Authorization': `Bearer ${accessToken.current}`,
'phosphor-device-id': `${deviceId}`,
'Accept': 'application/json',
};
return config;
};
const onRequestError = (error) => {
Promise.reject(error);
};
const onResponse = (response) => {
return response;
};
const onResponseError = async (error) => {
if (error.response.status === 401 && !oConfig._retry) {
oConfig._retry = true;
return refreshAccessToken().then((token) => {
accessToken.current = token;
apiCall.defaults.headers['Authorization'] = `Bearer ${token}`;
oConfig.headers['Authorization'] = `Bearer ${token}`;
return apiCall.request(oConfig);
})
.catch((error) => {
accessToken.current = null;
setAuth(false);
Promise.reject(error);
});
} else {
return Promise.reject(error);
}
}
apiCall.interceptors.request.use(onRequest, onRequestError);
apiCall.interceptors.response.use(onResponse, onResponseError);
In my nodejs code, I have middleware to check for incoming requests. It looks like this:
app.use((req, res, next) => {
console.log(`${req.method}: ${req.url}`);
if (Object.keys(req.query).length > 0) {
console.log('query params', req.query);
}
if (Object.keys(req.body).length > 0) {
console.log('body params', req.body);
}
next();
});
When the user submits an item with an expired access token, the response is "catched" by the axios response interceptor, and a new access token is generated and send back to the user. This works. Also, with return apiCall.request(oConfig);, the original request is retried. This does not work.
The first time , I get some logs about the request in my server console about the received req.body (thanks to the middleware). In my react native console, I see this body-object also (thanks to console.log('date before request', config.data); So when the request is retried, the full original body/data-object is send again to the server. But the second time, the req.body-object on the server (or what the server receives) is empty. I don't get any output in my node.js-middleware about the req.body-object, and my controller fails because it needs this content.
This only happens with POST requests (and req.body). When a "refresh-access-token" happens with a GET-request, the req.query-object is still complete in the second try.
What can possibly be wrong with this?
Edit: ofc I'm using express.json()
Try using error.config instead of oConfig
const onResponseError = async (error) => {
if (error.response.status === 401 && ! error.config._retry) {
error.config._retry = true;
return refreshAccessToken().then((token) => {
accessToken.current = token;
apiCall.defaults.headers['Authorization'] = `Bearer ${token}`;
error.config.headers['Authorization'] = `Bearer ${token}`;
return apiCall.request(error.config);
})
.catch((error) => {
accessToken.current = null;
setAuth(false);
Promise.reject(error);
});
} else {
return Promise.reject(error);
}
}

Node js api with front-end how to add book

I made an api with a database that stores books and I can get the book on the front-end like this
async function getBooks() {
try {
const response = await fetch("https://node-api-with-books.herokuapp.com/books");
return await response.json();
// console.log(books)
} catch (error) {
console.log("Error", error);
}
}
getBooks().then(book => {
console.log(book);
});
But I want to figure at how to add a book to the api
If I am getting this right and assuming that you configured you Api to accept Post requests then all you have to do is just send a post request to the backend API
async function addBook(bookData) {
try {
const response = await fetch("https://node-api-with-books.herokuapp.com/books", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(bookData),
});
return response.json();
} catch (error) {
console.log("Error", error);
}
}
and on the back end, you will parse the request with your middleware and then you can get the data from req.body
resource

why I m getting TypeError: Failed to fetch?

I got a fetched error type when trying to send data from a react app .
note that I m using cores.
and it s working fine on localhost with client side and not when hosting it online.
Note : I get result from json when using postman like this :
{
"success":"true",
"ID":"token"
}
this is the back-end code source in expressjs :
router.post("/sickers/user/login/", cors(), (req, res) => {
var values = req.body;
var pass = values.password;
var email = values.email;
if (pass !== null || pass !== "") {
try {
con.query("SELECT Password ,ID FROM `sickers` WHERE Email='" + email + "'", function(err, rows, field) {
if (err) {
console.log(err);
res.send("an error detected try later");
} else {
try {
if (pass == rows[0].Password) {
//create the signed function
jwt.sign(rows[0].ID, "secretkey", (err, token) => {
res.json({ success: "true", ID: token })
})
//session.session( )
} else {
res.json({ success: "false" });
}
} catch {
res.json({ success: "false" });
}
}
});
} catch (e) {
res.json({ success: "false" });
}
}
});
and client method is :
//submit values
const submithandler=async (e)=> {
e.preventDefault();
try{
console.log('start')
await fetch('url/api/sickers/user/login/',{
method:'post',
headers:{
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body:JSON.stringify({
password:password,
email:email
})
})
.then(response =>
{
console.log("response");
response.json().then(data =>
{
console.log(data);
if(data.success=="true")
{
sessionStorage.setItem('ID',data.ID);
window.location.reload();
seterr("");
}
else
{
seterr("try again");
}
});
});
}
catch(e)
{
console.log(e)
}
}
do I miss something here?
thanks in advance.
I solved this before by adding cores to .htaccess on server , or hosting the full project with it's back and front ends into the same server.

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

Server sends success even if didn't find anything

I send data from my input fields to my api:
$.ajax({
url: '/api/login',
type: 'GET',
dataType: 'json',
ContentType: 'application/json',
data: {formData},
success: (data) => {
console.log('SUCCESS')
console.log(data)
this.setState({
isInProcess: false
})
},
error: (jqXHR) => {
console.log(jqXHR)
console.log('ERROR')
this.setState({isInProcess: false})
}
})
on my server-side I have a function to see if I have required user in db:
async function findUser(data) {
try {
const user = await User.findOne({email: data.email,
password: data.password})
console.log('User was found')
return { user }
} catch (err) {
console.log('error', err)
throw err
}
}
which will be executed here:
app.get('/api/login', async (req, res) => {
const data = req.query
try {
const foundUserData = await findUser(data.formData)
return res.json(foundUserData)
} catch (err) {
return res.status(400).json(err)
}
})
It works fine, but if a user wasn't found in db i sends success anyway. Why?
await findUser(data.formData) won't throw error, return either null or user object. You may check something following
app.get('/api/login', async (req, res) => {
const data = req.query
try {
const foundUserData = await findUser(data.formData)
if(foundUserData && foundUserData.user) {
return res.json(foundUserData)
} else {
return res.status(400).json({message: 'User not found'});
}
} catch (err) {
return res.status(500).json(err)
}
})
It sends success because none of your queries error'ed, just because it didn't find anything does not mean that the query failed because it obviously succeeded in finding out if what ever you're looking for exists or not.
To send an error in case of not found you need to check if response is empty in which case you want to send error
When no user is find you get a null value. You may try to put more logic on your success parameter with that for example:
success: function (data) {
if(!!data && data != null) {
alert('Success');
} else {
alert('No data');
}
}

Resources