Unexpected token < in JSON at position 0 in express with firebase auth - javascript

I made an authentification system in express using firebase auth.
I created an endpoint in express like this :
app.post('/users/login', (req, res) => {
console.log('logare...');
firebase.auth().signInWithEmailAndPassword(req.body.email, req.body.parola)
.then(user => {
res.json({ succes: true, msg: "te-ai autentificat cu succes" });
})
.catch(err => {
console.log('date invalide');
res.json({ succes: false, msg: 'date invalide', errCode: err.code });
})
})
then I created a function in my font-end js file for send request to server :
const autentificare = async (email, parola) => {
return await fetch('https://cm-api-1.herokuapp.com/users/login', {
method: 'POST',
headers: {
'content-type': "application/json"
},
body: JSON.stringify({
email: email,
pasword: parola
})
})
.then(res => {
console.log(res.status)
return res.json();
});
};
In my app.js file I created submit event for verfy email and pasword:
form.addEventListener('submit', async e => {
e.preventDefault();
const email = emailDom.value;
const parola = parolaDom.value;
await autentificare(email, parola)
.then(data => {
if (data.succes) {
console.log('ok datele sunt valide')
} else {
console.log('date invalide')
}
})
});
When I submited the form in console it shows me this errors: POST https://cm-api-1.herokuapp.com/users/login 500 (Internal Server Error)and Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0 My api it's deployed on heroku.
I don't know what I missed

From my experience writing REST APIs, this error usually occur when there's some syntax error or an exception being caught in the API itself. The code looks fine but the HTML error 500 indicates it's not on the client end of things.
I have no experience with firebase and express, i've mostly written REST APIs with Swagger and php.

It is probably due to some issue with the JSON body content. Something like unescaped double quotes. Inspect what is being sent and received.
Read more about it here - https://www.kevinleary.net/syntax-error-unexpected-token-json-position-0/

Related

Issues With Netlify Lambda Function Response.. Keep Getting Undefined

I'm trying to setup a lambda function to authenticate, validate, and handle sending of a contact form..
I'm new to lambda functions so my code may be flawed, but no matter what I do I can't seem to modify the response that is sent back to my vue.js app.
I keep getting "response undefined" ...
Can some explain what I'm doing wrong, and maybe a better way to change the data returned based on what's going on in my function?
const axios = require('axios');
const FormData = require('form-data');
const AUTH_API_ENDPOINT = 'https://www.mywebsite.com/wp-json/jwt-auth/v1/token/'
const FORM_API_ENDPOINT = 'https://www.mywebsite.com/wp-json/contact-form-7/v1/contact-forms/1217/feedback'
const captchaThreshhold = 0.5
exports.handler = async function(event, context) {
const eventBody = JSON.parse(event.body)
const captchaSecret = process.env.CAPTCHA_SECRET
const captchaToken = eventBody.token
const stringFormData = eventBody.formData
let parsedFormData = JSON.parse(stringFormData)
let formData = new FormData()
var response;
//build a new FormData object
for ( var key in parsedFormData ) {
formData.append(key, parsedFormData[key])
}
// first step is to validate the captcha..
//let response_captcha
try {
response = await axios.post(`https://www.google.com/recaptcha/api/siteverify?secret=${captchaSecret}&response=${captchaToken}`,{})
} catch(err) {
return {
statusCode: 200,
body: JSON.stringify({
status: 'error',
message: 'Opps! The server tried to run an AI algorithm to determine if you are a spam robot, but the server did not respond properly so we are unable to continue contact form security verification... Please try again later or contact via phone instead. We appologize for the inconvenience.',
error: err.message
})
}
}
// if we're over the threshold we continue and get a fresh JWT
if (response.data.score >= captchaThreshhold) {
// let response_jwt
try {
response = await axios.post(AUTH_API_ENDPOINT,{
username: process.env.AUTH_USERNAME,
password: process.env.AUTH_PASSWORD,
}).then(res => {
// JWT token returned something.. lets try to submit our form data with authentication code..
axios.post(FORM_API_ENDPOINT, formData, {
headers: {
'Authorization': `Bearer ${res.data.token}`,
'Content-Type': 'multipart/form-data; charset="utf-8"',
...formData.getHeaders()
}
})
.then( res => {
console.log('>> response came back from the Form endpoint : ',res.data.status, res.data.message)
return {
statusCode: 200,
body: {
status: res.data.status,
message: res.data.message
}
}
})
.catch( err => {
console.log('>> something went wrong while trying to submit formData to form endpoint ',err.response.data);
return {
statusCode: 200,
body: JSON.stringify({
status: 'error',
error: err.message,
message: 'Yikes! The form data was processed and sent to our email server but there was no response back. Our developer will look into this shortly. In the meantime, please try again later or contact via phone. We appologize for the inconvenience.'
})
}
})
}).catch( err => {
console.log('>> something went wrong while trying to fetch JWT from endpoint ',err.response.data);
return {
statusCode: 200,
body: JSON.stringify({
status: 'error',
error: err.message,
message: 'Yikes! The form data was processed and sent to our email server for authentication but got no response back.. This is a server issue so our developer will look into this shortly. In the meantime, please try again later or contact via phone. We appologize for the inconvenience.'
})
}
})
} catch(err) {
return {
statusCode: 200,
body: JSON.stringify({
status: 'error',
error: err.message,
message: 'Yikes! The form data was processed and sent to our email server but the server was unable to authenticate the request. This is a server issue so our developer will look into this shortly. In the meantime, please try again later or contact via phone. We appologize for the inconvenience.'
})
}
}
} else {
// user failed the captcha test.. is probably a robot..
return {
statusCode: 200,
body: JSON.stringify({
status: 'error',
message: "Error! Captcha Failed: our AI algorithms tried to determine if you are a robot or a human, it seems they couldn't decide, therefor for security reasons your form submission was blocked. Perhaps try again later, or contact via phone. We appologize for any inconvenience. :("
})
}
}
//send back the response..
return response
}
Maybe something more like:
exports.handler = function(event, context) {
return new Promise((resolve, reject) => {
axios.post(...args).then(response => {
if(bool){
axios.post(...moreArgs).then(response => {
resolve('ok!')
}).catch(reject)
} else {
reject('not bool!')
}
}).catch(reject)
})
}
I feel like async / await makes this more complicated than without it.

My sent data using axios is returned in config, not data

I am building my web app on NextJS NodeJS and Express, I am running two servers on localhost 3000 for next and 9000 for express.
I have a form with two input fields and I am sending the state with axios post to the url with data, on the server-side I am receiving that request and sending back the same received data as a response.
I get the response from server with data: success and my data in config.data
Why is my data in config data and how can I get it out from this JSON so I can pass it to a variable.
As for grabbing the data from the config.data, I have tried for loops but they either push 56 elements of 56 numbers to the empty array or don't do nothing.
Client side:
state = {
bank_name: '',
account_number: ''
}
...
onSubmit = (e) => {
e.preventDefault()
axios.post('http://localhost:9000/api/bank', {
bankName: this.state.bank_name,
accNumber: this.state.account_number
})
.then(res => {
console.log(res)
}).catch(err => console.log(err))
}
Server side:
router.post('/', (req, res) => {
const {reqData} = req;
res.send(reqData);
})
Console log from client side ( console.log(res) ):
{
config: {
url: "http://localhost:9000/api/bank",
method: "post",
data: '{"bankName":"some new bank","accNumber":"39276542934235"}'
},
data: "success",
headers: "...",
request: "...",
status: 200,
statusText: "OK",
__proto__: Object
}
...
When I target res.config.data.bankName I get undefined.
I believe this has to do with the server response being as it is, or not parsing the data server receives in the first place, or it is due to promises.
Any input would be helpful, thanks
That res.config.data is string so parse it first JSON.parse(res.config.data) and then access the bankName.
Also you must be using body-parser at the express end. And so post data resides in req.body you should send that back not the whole req IMO.
Express:
router.post('/', (req, res) => {
const reqData = req.body;
return res.send(reqData);
});
Axios: (returned data should be in res.data)
axios.post('http://localhost:9000/api/bank', {
bankName: this.state.bank_name,
accNumber: this.state.account_number
})
.then(res => {
console.log(res.data);
}).catch(err => console.log(err))
}

bcrypt.compare cannot set response headers in nextjs

I can't seem to get the correct response headers when my code enters bcrypt.compare. I thought it was a cors issue at first but I still get the correct response if I entered the wrong and "user does not exist" is displayed.
Here's my api server side code in express
router.post("/api/signIn", (req, res) => {
const { user, password } = req.body;
const queryString = "SELECT * FROM users WHERE user_id = ?";
db.query(queryString, [user])
.then(result => {
if (result.length > 0) {
const hash = result[0].password;
//here bcrypt.compare works server side or with cURL but won't set the response headers in the browser
bcrypt
.compare(password, hash)
.then(same => {
if (same === true) {
console.log("correct password");
res.status(200).json({
code: 200,
message: "correct password"
});
} else {
res.status(401).json({
code: 401,
message: "incorrect password"
});
}
})
.catch(err => console.log(err));
} else {
//this one works though and i can get the response in the browser so it can't be a cors issue
console.log("user does not exist");
res.status(200).json({
code: 401,
message: "User does not exist"
});
}
})
.catch(err => {
console.log("error" + err.message);
});
});
and this is the test function i use in react
const signIn = () => {
fetch("http://localhost:5000/api/signIn", {
method: "POST",
body: JSON.stringify({
user: userName,
password: password
}),
headers: {
"Content-Type": "application/json"
},
})
.then(res => res.json())
.then(response => alert(response.code + response.message))
.catch(err => alert(err));
};
so if i entered the wrong username that is not in the database, the alert function would show (code401User does not exist) but if i entered the correct user bcrypt.compare() doesn't seem to set the response for both correct and incorrect passwords and i would get (TypeError: failed to fetch). testing the api in cURL works though.
Got it, I forgot to put event.preventDefault() on the fetch function.

ReactJS and Node.JS [JSON.parse: unexpected character at line 1 column 1 of the JSON data]

I'm getting struggle with this code, so I need a third eye on this to find a solution.
I'm developing a ReactJS app with a REST API with Node.JS (Express), and I'm getting this error:
SyntaxError: "JSON.parse: unexpected character at line 1 column 1 of the JSON data"
I'm using Sequelize ORM to work with Models and Database in Node.JS.
I'm also using CORS module for Node.JS.
This implementation works fine.
// Node.js Route for login
const router = require('express').Router();
const User = require('user');
router.post("/login", async (req, res) => {
try {
await User.findOne({
where: {
email: req.body.email,
password: req.body.password,
}
}).then((user) => {
if (!user) {
return res.send({message: "Login error!"});
} else {
const userData = {id: user.id, email: user.email};
res.send({"user": userData});
}
}).catch((err) => {
return res.send(err);
});
} catch (err) {
return res.send(err);
}
});
// ReactJS for login
loginFunction(e, data) {
e.preventDefault();
fetch('http://localhost:4500/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(json => {
this.setState({'user': json['user']});
})
.catch((err) => {
console.log(err);
this.setState({errors: "Login error"})
});
}
On the other hand, this implementation do not work properly and throws the SyntaxError above:
// Node.JS for Posts
const router = require('express').Router();
const Post = require('post');
router.get("/posts", async (req, res) => {
try {
await Post.findAndCountAll()
.then((posts) => {
res.send({"posts": posts});
}).catch((err) => {
return res.send(err);
});
} catch (err) {
return res.send(err);
}
});
// ReactJS for Posts
postsFunction() {
fetch('http://localhost:4500/posts', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(json => {
this.setState({'posts': json.posts.rows});
})
.catch((err) => {
console.log(err);
this.setState({errors: "Posts error."})
});
}
As you can see both implementation have little differences, What am I missing?
PS: When I test the 2nd implementation on Postman, data is retrieving successfully.
try removing headers when using GET method
headers: {
'Content-Type': 'application/json'
}
Try to use res.json instead of res.send in the node js function that cause the error.
I found the issue!
I follow the (#vengleab so) suggestion:
console log response instead of response => response.json()
I'm realize that response returns an object like this:
Response: {
body: ReadableStream
locked: false
<prototype>: object { … }
bodyUsed: false
headers: Headers { }
ok: true
redirected: false
status: 200
statusText: "OK"
type: "basic"
url: "http://localhost:3000/admin/undefined/posts"
}
The URL attribute contain an undefined value, so when I try to console.log the .env variable API_URL that contains the localhost URL used in this line:
fetch('http://localhost:4500/posts', {
That in real function is:
fetch(process.env.API_URL + '/posts', {
The result of the console.log was undefined.
As it is explained in Create React App docs, the environment variables must start with the prefix REACT_APP_.
Finally the line works as:
fetch(process.env.REACT_APP_API_URL + '/posts', {
I found that it was because my front end react url pointed to the same url as my backend server.js running mongodb. Also clearing the cookies on the browser seems to have helped as well.

NodeJs - fetch request from client always returns a 200 status response from the server regardless if there was an error updating the DB

I am using a fetch() request from the client to PUT updated user data to the backend, to then be saved into a DB. So far, the all of the route is working fine, verified and tested in Postman.
In this User Update route, there is an if statement that checks for an error when searching for the user in the database, and if this error is thrown, it sends a response of 404 and a message to the client.
When I make the fetch() request from the client to this route, regardless if there is an error, the response is always a status 200, and does not include any response from my route. I need the client to be able to handle the potential errors the routes might produce. For example with this user update route, if the user is not found in the database for whatever reason, an error and message is returned, so the client needs to know this.
Here is some code:
Client-side:
fetch(`http://localhost:3000/users/${userId}`, {
method: "put",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(userData)
}).then(response => console.log(response))
.catch(err => console.log(err));
Here in the client, I am using console.log() to visualize everything. When the response returns, I get back:
Response {type: "basic", url: "http://localhost:3000/users/accounts/", redirected: false, status: 200, ok: true, …}
Server-side route controller:
exports.user_update = (req, res) => {
const { params, body } = req;
const { userid } = params;
User.findByIdAndUpdate({ _id: userid }, body, { new: true }, (err, user) => {
if (err)
res.send({
status: 404,
message:
"There was an issue finding and updating the user on the server."
});
else
res.send({
status: 200,
user
});
});
};
Now here on the server, I anticipated the response of the fetch() to be either the 404 error or the 200 success along with their payloads. Neither are returned in a response from the server. Instead as mentioned above, I am getting a generic 200 ok response simply letting me know the fetch() made a connection to the route. This route(along with the others) has been tested in Postman, and all work as anticipated returning the expected responses.
What am I not understanding here? Is my idea of using a fetch() request in this manner wrong? I feel like I might be close, but that's just my ignorant guess. Thank for reading!
I figured out the solution.
The fetch request was wrong, here is the update:
fetch(`http://localhost:3000/users/${userId}`, {
method: "put",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(userData)
}).then(response => response.json())
.then(response => console.log(response))
.catch(err => console.log(err));
I had to call response.json() to parse the response as a JSON object.
According to express documentation you sent status as a field of JSON. To correctly send http status replace your res.send(...) with
res.status(404).send("There was an issue finding and updating the user on the server.");
and
res.send(user);
You are sending the status field inside your payload, which is not parsed by fetch API.
To solve this you could something as below
exports.user_update = (req, res) => {
const { params, body } = req;
const { userid } = params;
User.findByIdAndUpdate({ _id: userid }, body, { new: true }, (err, user) =>
{
if (err)
res.status(404).send({
message: "There was an issue finding and updating the user on the server."
});
else
res.status(200).send({
user
});
});
};

Categories