Send data from Javascript file to backend Node.js - javascript

I'm building my first project so I'm pretty new to Js, Node Js, etc. My question is how do you send data from Javascript file to the backend in this case Node.js file, the Javascript file is link to the html file.
MY HTML:
<button type="button" class="btn btn-light bn" id="1"><span
class="dif">3/8"</span> Q2.15</button>
MY JAVASCRIPT:
const button = document.getElementById('1');
button.addEventListener('click', function(e) {
fetch('/clicked', {
method: 'POST',
body: JSON.stringify({ id: e.currentTarget.id }),
})
.then(function(response) {
if(response.ok) {
console.log('Click was recorded');
return;
}
throw new Error('Request failed.');
})
.catch(function(error) {
console.log(error);
});
});
NODE JS CODE:
app.post('/clicked', (req, res) => {
const click = JSON.parse(req.body).id;
Product.findOne({id: click}, function(err, foundLList) {
if(err) {
console.log(err);
} else {
console.log(foundLList);
}
}
);
});
What I´m trying to accomplish is to send the id of the button clicked to the backend(node.js) but is not working i tried to console.log thr req and req.menu and when I do req.menu appears only {} and when I add .id to the request is shows undefined.

In your fetch() call, you should specify the Content-Type header as application/json. This way, your server knows how to handle it.
fetch('/clicked', {
method: 'POST',
body: JSON.stringify({ id: e.currentTarget.id }),
headers: {
'Content-Type': 'application/json'
}
})
On the Node.js side, it looks like you're using Express. Make sure you're also using the Body Parser middleware, which can handle your JSON.
const bodyParser = require('body-parser');
app.use(bodyParser.json());
Alternatively, for newer/current versions of Express, you can use express.json().

Related

How to handle POST request data with Express

I have an alert button on the client side with an event listener that is trying to send data to the server. Here is my client side code:
alertBtn.addEventListener("click", () => {
axios
.post("http://localhost:3000/", {
userEmail: "test",
selectedPrice: "test",
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
});
Here is my express code on the server:
app.post("/", (req, res) => {
console.log(req.body);
res.json({ requestBody: req.body });
});
I am trying to handle the data but the body of the request is just an empty object ({}).
When sending JSON need to set the appropriate headers, as express will only decode the body is the incoming request have the right headers see here
But if you would like the answer upfront its
axios
.post("http://localhost:3000/", {
userEmail: "test",
selectedPrice: "test",
}, {
headers: {
'content-type': 'application/json'
}
})
//By default axios should do this, so maybe middlewares are missing server side?
also as commenter stated im presuming you already set your middlewares infront of this code....

Empty body at server side when using fetch

I am trying to send html form data to server via a fetch 'POST' request but at server side I am getting Empty request body. I have already tried different solutions provided on stack overflow but none of them is working at my end. could anyone please help me identify where I am going wrong.
I have the form with id 'signup-form' in my html file
client side JavaScript the code goes like below:
const myForm = document.getElementById('signup-form')
myForm.addEventListener('submit', (e) => {
e.preventDefault()
const myForm = document.getElementById('signup-form')
const data = new FormData(myForm)
const option= {
method: 'POST',
headers: {
'Content-type': 'application/json'
},
body:JSON.stringify(data)
}
fetch('/login', option).then(
response => response.json()
).then(
data => console.log(data)
).catch(
error => console.log(error)
)
})
Server side express js code goes like below
app.use(express.urlencoded({ extended: false}))
app.use(express.json())
app.post('/login', (req, res) => {
console.log('url is', req.url)
const info = req.body;
console.log('info is:', info)
res.status(201).json({ 'submitted': true })
})
app.listen(3000, () => {
console.log('listening on port 3000')
})
With FormData you cannot POST application/json, because that is not on the list of content types supported by a form element.
Instead, write something like
const data = {element1: "value", element2: "value2", ...};

When I post data with fetch post, I don't receive data

I have a problem with fetch post, I want to send data to an url but it doesn't work..
function TodoTaskForm () {
const taskContentInput = useRef(null)
const handleSubmit = async (e) => {
e.preventDefault()
fetch('/api/tasks', {
method: 'POST',
body: JSON.stringify({content: taskContentInput.current.value})
})
}
return (
<form onSubmit={handleSubmit} className="__component_todolist_form_container">
<input type="text" name="task" ref={taskContentInput} placeholder="nouvelle tâche.."></input>
</form>
)
}
In my component, I'm doing this and in my express server :
app.post('/api/tasks', (req, res) => {
console.log(req.body)
console.log('request received!')
})
When I test, i receive the request but req.body return "{}" in my console, I don't understand, im using app.use(express.json()) but it doesn't work, I have even try to use body-parser but...
So please, I need help.. thank you!
You need:
A body parser which matches the data being send. You've switched from sending form encoded data to sending JSON. Note that Express has built-in body parsing middleware and does not need the separate body-parse NPM module.
A Content-Type header on the request which states what format the data is in so the correct body parser can be triggered.
Such:
app.post('/api/tasks', express.json(), (req, res) => {
console.log(req.body)
console.log('request received!')
})
and
fetch('/api/tasks', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({content: taskContentInput.current.value})
})

JSON is becoming empty upon hitting server code

I am sending a fetch request with a JSON payload from my webpage like this:
let raw = JSON.stringify({"name":"James","favourite":"books"})
var requestOptions = {
method: 'POST',
body: raw
};
let send = () => {
fetch("http://mywebsite.herokuapp.com/send", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
}
On the server side I am getting an empty body {}. Here is the code I use to monitor that:
app.post('/send', (req, res) => {
console.log(req.body)
})
When I send the exact same code generated with Postman to server — somehow everything works fine, and I get the correct JSON. Please help me understand why that is.
On the server, req.body will be empty until you have middleware that matches the content type in the POST and can then read the body from the response stream and populate req.body with the results.
// middleware to read and parse JSON bodies
app.use(express.json());
app.post('/send', (req, res) => {
console.log(req.body);
res.send("ok");
});
And, then on the client side, you have to set the matching content-type, so the server-side middleware can match the content-type and read and parse it:
const requestOptions = {
method: 'POST',
body: raw,
headers: {
'Content-Type': 'application/json'
},
};

Sending an image with axios to Node.js and then using it further

I am trying to upload an image from the front-end, post it with axios to back-end (node.js) and then from there post it again to the GroupMe image service.
The main thing is to avoid using the API token in the front-end and so I was trying to first send a request to the back-end and then send the actual API request to the GroupMe image service which expects to get FormData of an image and sends back converted image URL.
I have tried to send FormData directly to the GroupMe image service from the front-end and everything works fine. However, in order to do so, I had to store the token in the front-end, which is not a good idea I believe.
The working code below:
let config = {
headers : {
'X-Access-Token': myToken,
'Content-Type' : 'multipart/form-data'
}
}
let fd = new FormData()
fd.append('name', 'image')
fd.append('file', fileToUpload)
axios.post'(https://image.groupme.com/pictures', fd, config)
.then((response)=>{
console.log(response)
})
.catch(err =>{
console.log(err.response)
})
What I need to happen instead is to send the request to the back-end like so:
axios.post(process.env.baseUrl+'/messengerRequests/upload-file/', fd, config)
.then((response)=>{
console.log(response)
})
.catch(err =>{
console.log(err.response)
})
And now in the back-end somehow be able to get that FormData and then create another post request to the GroupMe image service as I initially did in the front-end.
sendMessage: async(req, res) => {
axios.post('https://image.groupme.com/pictures', ???, config)
.then((response)=>{
res.send(response)
})
.catch(err =>{
console.log(err.response)
})
}
I do not know where it appears in the axios request. There is nothing in the req.body or req.params so I am not able to simply pass it further for the next post.
Is there a way somehow pass this FormData again?
Or maybe there is a way to safely use the token in the frond-end?
So, it should be relatively straightforward to post the image to GroupMe using Node.js and Express / Multer / Request. I've gone for Request rather than Axios on the backend since I'm more familiar with the API, but it's the same difference really.
Node.js Code (index.js)
const request = require("request");
const express = require("express");
const multer = require("multer");
const upload = multer();
const app = express();
const port = 3000;
const myToken = "" // Your API token goes here.
app.use(express.static("./"));
/* Here we take the image from the client and pass it on to GroupMe */
app.post("/uploadFile", upload.any(), (req, res) => {
sendImageToGroupMe(req, res);
});
function sendImageToGroupMe(req, res) {
const options = {
uri: "https://image.groupme.com/pictures",
body: req.files[0].buffer,
method: "POST",
headers: {
"X-Access-Token" : myToken
}
}
request(options, (err, response, body) => {
console.log("Request complete: Response: ", body);
if (err) {
console.error("Request err: ", err);
res.status(500).send("Upload failed: ", err.message);
} else {
res.status(201).send("Upload successful: GroupMe response: " + body);
}
});
}
app.listen(port);
Client side
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function uploadFile() {
var fileToUpload = document.querySelector('input[type=file]').files[0];
let config = {
headers : {
'Content-Type' : 'multipart/form-data'
}
}
let fd = new FormData()
fd.append('name', 'image')
fd.append('file', fileToUpload)
axios.post('http://localhost:3000/uploadFile', fd, config)
.then((response)=>{
console.log("Image posted successfully: ", response);
showOutput("Image posted successfully: " + response.data);
})
.catch(err =>{
console.error("Image post failed: ", err)
showOutput("Image post failed!");
})
}
function showOutput(html) {
document.getElementById("output").innerHTML = html;
}
</script>
</head>
<body style="margin:50px">
<input type="file" onchange="uploadFile()"><br>
<p id="output"></p>
</body>
</html>
All files go in the same directory. You can go to http://localhost:3000/ to test the index.html code, this will be served by the Node.js server as a static file.
I get a response like below from the GroupMe API:
{
"payload": {
"url": "https://i.groupme.com/157x168.png.940f20356cd048c98478da2b181ee971",
"picture_url": "https://i.groupme.com/157x168.png.940f20356cd048c98478da2b181ee971"
}
}
We'll serve locally on port 3000, so to start the server:
node index.js
If you are using Express, you will need something to process the FormData. I have used multer for something similar before. I had to save the files into local storage, then resend the file with axios.

Categories