Problems with fetching react.js/node.js - javascript

I'm trying to pass some datas from frontend to backend.
Here the code lines....
FRONTEND
handleSubmit = (event) => {
alert('A form was submitted: ' + this.state);
fetch('http://localhost:5000/store-data', {
method: 'POST',
/*mode: 'cors',*/
headers: {
'Content-Type': 'application/json',
},
// We convert the React state to JSON and send it as the POST body
body: JSON.stringify(this.state)
}).then(function(response) {
console.log(response)
return response.json();
});
console.log("Sono entrato");
event.preventDefault();
}
BACKEND
app.post("/store-data", (req, res) => {
let data = { name: req.body.username };
console.log(data.name);
console.log(JSON.stringify(req.body));
res.json("Hello");
});
All the console.log works well.
But if I go on the "localhost:5000/store-data", I get this error:
"CANNOT GET /store-data/ PAGE NOT FOUND 404"
Thanks
I add tis code and now seems to work:
app.get("/store-data", (req, res) => {
let data = { name: req.body.username };
console.log(data.name);
console.log(JSON.stringify(req.body));
res.send("Hello");
});
But I have to keep both the app.get() and the app.post() to work.
I think that is not the correct way.
Thanks

I solve it. The problem was that i make a mistake with the fetch method and I get undefined in the return response.json.
Now in the post method res.send work.
It was an error on the Frontend code not in the Backend.
In my case I don't need anymore app.get(....), but only the app.post(.....).

Related

POST method to express server returning 404 [duplicate]

This question already has an answer here:
Express routes parameters
(1 answer)
Closed last month.
I'm trying to send a POST to my server, in order to edit a user's details. I've made sure it's sending to the right URL, however get a 404 response. GET requests work fine, however my POST doesn't seem to get through for whatever reason. I've been searching for solutions for a while, with no luck hence posting here!
user.js (server side)
userRoutes.route('/user/update/:id').post(function (req, response) {
let db_connect = dbo.getDb("preview");
let myquery = { _id: ObjectId(req.params.id) };
let newValues = {
$set: {
name: req.body.name,
user_name: req.body.user_name
},
};
db_connect
.collection("users")
.updateOne(myquery, newValues, function (err, res) {
if (err) throw err;
console.log('user updated');
response.json(res);
})
});
middleware
export const updateUser = async (id, userDetails) => {
const endpoint = `${serverIp}/user/update/?id=${id}`;
try {
const response = await fetch(endpoint, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(userDetails)
})
const result = await response.json();
return result;
} catch (error) {
console.log(error)
}
}
and a simple function to handle submitting
function handleSave() {
const newUserDetails = {
name: accountHolder,
user_name: accountUsername
};
updateUser(userId, newUserDetails);
}
Under networking in dev tools I can see the URL is indeed correct, so I can't see why this isn't working
chrome dev tools
Any help would be greatly appreciate it!
I've tried sending a basic response (i.e. a string instead of object), changing the endpoint, and more all to no avail
It seems like you are passing the id as a query param and not as part of the path
const endpoint = `${serverIp}/user/update/?id=${id}`;
^
What I can see from first glance is that in server-side you are using request parameter for id, but in the client you're sending id as a request query

How do I get the POST data from a netlify serverless function?

Here is the code for my server which works fine. I am trying to achieve this with netlify's serverless functions which I have pasted further below.
CODE ON STANDARD SERVER-HEROKU
const ratingController = {};
const Rating = require("../models/ratingModel");
ratingController.getAllRatings = async function (req, res) {
const rating = await Rating.find();
res.status(200).json({
status: "success",
data: rating,
});
};
ratingController.createOneRating = async function (req, res) {
console.log(req.body);
req.body.userIp = req.headers["x-forwarded-for"];
const rating = await Rating.create(req.body);
// const rating = new Rating(req.body);
// await rating.save();
res.status(200).json({
status: "success",
data: {
rating,
},
});
};
PART 1 - GET REQUEST
Here's my code for the getAllRatings and it works fine
SERVERLESS FUNCTION - NETLIFY
const { MongoClient } = require("mongodb");
require("dotenv").config();
exports.handler = async function getData(event, context) {
const client = await MongoClient.connect(process.env.DB, {
useUnifiedTopology: true,
useNewUrlParser: true,
});
const db = client.db();
try {
const slug = event.queryStringParameters.id;
const data = await db.collection("collectionName").find({ slug }).toArray();
client.close();
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
status: "success",
data: data,
}),
};
} catch (error) {
console.log(error);
return {
statusCode: 400,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
status: "fail",
message: error.message,
}),
};
}
};
My first question for the above is
Just because it works may not mean it's the right way to do it.. I had a few concerns if calling the database each time there's a call is correct and then placing the code the way I have, if it's the way it should be. It's all based on testing and random research. There's no real method being followed so would appreciate some guidance on a more efficient method to do this.
Normally on a regular server the database connection is done just once.. and here I seem to be doing it every time and I am a bit confused if that's ok or not..
PART 2 - POST REQUEST
Here's my code for the POST request createOneRating
SERVERLESS FUNCTION - NETLIFY
const { MongoClient } = require("mongodb");
require("dotenv").config();
exports.handler = async function createRating(event, context) {
const client = await MongoClient.connect(process.env.DB, {
useUnifiedTopology: true,
useNewUrlParser: true,
});
const db = client.db();
try {
console.log(event);
const rating = await db.collection("ratings").insertOne(event.body);
client.close();
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
status: "success",
data: rating,
}),
};
} catch (error) {
console.log(error);
return {
statusCode: 400,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
status: "fail",
message: error.message,
}),
};
}
};
This one does not work as it says
{
"status": "fail",
"message": "Cannot create property '_id' on string ''"
}
And I guess that's because event.body is not where the data is.. but I am not sure how to get the POST data in a serverless deployment.
So my second question is
How do I retrieve the data sent by a POST request. As there's no request parameter I am a bit confused.
Also I'd like to add the IP of the user so other than the POST data I'd also need some help on how to do this
req.body.userIp = req.headers["x-forwarded-for"];
Based on my own research, I have answers to the questions and am placing them here for my own reference and for those who might face a similar situation in the future.
Question 1 : Is it ok to make a database connection on every call that's made to a serverless function
It seems it's ok to do this and for those, like me, who thought that maybe it was not the right way to do it, it's definitely not the wrong way. Maybe there's an efficient way to do this and I'd be open to learn more about this if possible. But for now, it's good to know that it's not wrong to connect to the database each time you make a call.
Question 2: How to make a POST request on a serverless as there's no request parameter
I was not aware that the event parameter is in fact a replacement for the request parameter and that the headers and body are properties of the event object and can be accessed in the same way ie event.body and event.headers. Here's a link that could save you some time to confirm this.
(https://docs.netlify.com/functions/build-with-javascript/#synchronous-function-format)
And if you, like me, don't know if a serverless function can be defined as GET or POST or run into an issue where the POST request gets converted into a GET when making a function call here's a link that would help.
How to define Netlify function endpoint as POST?

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.

Route handler in express is not invoking anything?

I have made a simple textbox which accepts
Youtube Video URL
which slices it's video ID and use fetch to send data to my express server. I am using Youtube Data API v3
//after clicking button sends data
//input fields are defined already.
const sendData = (event) => {
event.preventDefault();
const filterUrl = input2.value.indexOf('&') != -1 ? input2.value.slice(0, input2.value.indexOf('&')) : input2.value;
const url = new URL(filterUrl).searchParams.get("v");
fetch('/', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
urlname: url.toString()
})
})
.then(function(res) {
console.log(res)
})
.catch(function(error) {
console.log(error)
});
}
Here is my Express Handler :
//defined routes and PARAMETER variable is globally defined
app.route('/')
.get((req, res) => {
res.render('container/index', {
title: 'Hello User!',
content: 'Welcome to youtube Comment viewer'
});
})
.post((req, res) => {
console.log("hello")
PARAMETER = req.body.urlname;
console.log(PARAMETER);
res.redirect('/randomCommentView');
});
//get request
app.get('/randomCommentView', (req, res) => {
console.log("inside");
Comments(PARAMETER)
.then((data) => {
res.render('container/comment', {
Comment: 'fgfg'
})
}).catch(err => {
if (err) res.status(404).render('container/index', {
notFound: `Your request couldn't be completed ERR: ${err}`
})
})
console.log(req.body);
});
But when i submit my Youtube video url, The page stays on the same route.
Here's the image of my output:
So it seems like the routes are being called but the page URL is not changing in the web browser .Does anyone know the possible reason for this.
Thanks,
Regards.
Since you're using javascript to make your request, only the javascript will follow your redirection.
What you can do is instead of sending a redirection from the server, send a special code that will trigger a manual redirection (window.location.href = ...) in your client-side javascript code.

Axios POST request fails with error status code 500: Internal Server error

I'm trying to send a POST request locally with a username and password in the body through Axios.
I'm deploying a Flask app on http://127.0.0.1:5000/login, which handles the /login route. The POST request fails with the following error
POST http://127.0.0.1:5000/login 500 (INTERNAL SERVER ERROR)
Error: Request failed with status code 500
at createError (createError.js:16)
at settle (settle.js:18)
at XMLHttpRequest.handleLoad (xhr.js:77)
I researched a bit and thought it might be a problem with CORS, but this doesn't seem to be the case because I tried an Axios GET request and it worked fine (response logged properly). Here's part of my code
axios.get("http://127.0.0.1:5000").then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
})
axios.post("http://127.0.0.1:5000/login", {
username: this.state.username,
password: this.state.password
}).then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
})
Looking at Chrome DevTools, I can see that the POST request payload is properly populated. I then tried printing out the keys server-side in the Flask app using the following code, but I got nothing, empty. (which was expected since the POST request failed)
dict = request.form
for key in dict:
print('form key '+dict[key])
HOWEVER using Postman with the corresponding keys and values works properly and returns a response and prints out the keys (see above). Where is the failure coming from? Why would the POST request fail when a GET seems to work just fine?
Feb 2021. Wasted 2 hours on this. Not much help on this famous library on internet.
Solution:
In the catch block, the error which will always be 500 internal server error
so, use error.response.data instead of error.
Code:
try {
let result = await axios.post( // any call like get
"http://localhost:3001/user", // your URL
{ // data if post, put
some: "data",
}
);
console.log(result.response.data);
} catch (error) {
console.error(error.response.data); // NOTE - use "error.response.data` (not "error")
}
Update:
I ended up writing a common function for handing error:
File: common.app.js
export const errorUtils = {
getError: (error) => {
let e = error;
if (error.response) {
e = error.response.data; // data, status, headers
if (error.response.data && error.response.data.error) {
e = error.response.data.error; // my app specific keys override
}
} else if (error.message) {
e = error.message;
} else {
e = "Unknown error occured";
}
return e;
},
};
More info: https://github.com/axios/axios#handling-errors
So I also got stuck in the same problem and the solution that I found was something like this :
let data = JSON.stringify({
username: this.state.username,
password: password
});
const response = axios.post(url,data,{headers:{"Content-Type" : "application/json"}});
This solution worked for me.
Apparently Axios didn't take kindly to the raw JSON object
{username: this.state.username, password: password}
but passing the data into a FormData object seemed to work just fine!
After working 2 hours, I realized I made a mistake about the body and data. So, in the axios make sure you pass the data like this.
async function loadToken(){
try{
response = await axios({
url: ``,
headers: {
'Authorization': '',
'Content-Type': '',
},
data: '',
method: 'POST'
});
let data = response.data;
return {
tokenInfo:data,
timestamp:new Date().getTime()
}
} catch(err) {
console.log("err->", err.response.data)
return res.status(500).send({ret_code: ReturnCodes.SOMETHING_WENT_WRONG});
}
}
My previous code pass the data like this, which is wrong
async function refreshToken(){
try{
let headers = {
authorization: '',
'Content-Type': ''
}
let url = ``
let body = {
grant_type: '',
refresh_token: global.tokenInfo.refresh_token
}
data = await axios.post(url, body, {headers});
let data = response.data
console.log(data)
return {
tokenInfo:data,
timestamp:new Date().getTime()
}
} catch(err) {
console.log("err->", err.response)
return res.status(500).send({ret_code: ReturnCodes.SOMETHING_WENT_WRONG});
}
}
Simply try my first code, hope that solves your issue.
Most of the time it happens because of using wrong content type header.
Open postman and see "Body" tab. There you can find the content type of your post data. It's also accessible from "Headers" tab. There should be a Content-Type header. The correct format of data you send through a POST request depends on Content-Type header. for example, json content type requires a json (javascript object) data or form-data content type requires a FormData.
To set a header in axios, change the code like this:
axios.post("http://127.0.0.1:5000/login", {
username: this.state.username,
password: this.state.password
}, {
headers: {'Content-Type': 'application/json'}
}).then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
})
I had similar error i had the JSON capital and it should have been lowercase

Categories