Empty body at server side when using fetch - javascript

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", ...};

Related

How do I make a live search result in node.js and mongoDb

I am trying to implement a feature where I have an input on this route to make a live search of employees in the database
app.get('/delete' , isLoggedIn , (req , res) => {
res.render('pages/delete')
})
This route serves the search input. How do I create a live search based on a keyup event listener that sends the data to mongoDb/mongoose to search and return the results on the page?
I know how to do the event listener to get what is typed like so which is in the delete.js file
const deleteSearchInput = document.querySelector('#search-input');
deleteSearchInput.addEventListener('keyup' , (e) => {
let search = e.target.value.trim()
})
How do I send the value "e" to a post route to do the search and return it to the page
AJAX (using the JavaScript fetch API). AJAX allows JavaScript to send requests to the server without reloading.
const deleteSearchInput = document.querySelector('#search-input');
deleteSearchInput.addEventListener('keyup' , (e) => {
let search = e.target.value.trim();
fetch('/delete', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({search})
}).then(res =>
res.json()
).then(data => {
console.log(data.result); // <-- success!
}).catch(err => {
alert('error!');
console.error(err);
});
});
Then you have changes to make to the server side. Since you're sending a POST request, you need to create a handler to POST:
app.post('/delete', isLoggedIn, (req, res) => {
res.send('success!');
});
This will handle post requests, and only post requests. Now to get the value of whatever you sent to the server, we need to use an npm package called body-parser, which parses the incoming request. Run the following command in shell:
npm i body-parser
Then at the top of your server file before declaring your routes import and use the body-parser library:
const bodyParser = require('body-parser');
app.use(bodyParser.json()); // <-- add the JSON parser
Finally change your handler again:
app.post('/delete', isLoggedIn, (req, res) => {
const { search } = req.body;
console.log(search);
// ... do whatever you want and send a response, e.g.:
const result = 'my awesome message';
res.json({ result });
});
And that's how you do it.

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

Sending state for an Axios POST and data not showing in req.body

I'm using React and want to make a POST request using Axios. I'm trying to send form data to my Node backend.
I am trying to send an object in the POST request which is the state holding all of the user's inputs to a form.
React
const [formDetails, setFormDetails] = useState({})
const handleFormChange = (evt) => setFormDetails({ ...formDetails, [evt.target.name]: evt.target.value })
const sendInvoice = async (formDetails) => {
const response = await axios.post('/api/new_invoice', formDetails)
console.log(response)
}
Node route
module.exports = (app) => {
// Create a new invoice
app.post('/api/new_invoice', async (req, res) => {
console.log('making a new invoice...')
try {
console.log(req.body)
res.send(req.body)
} catch (err) {
console.log(err)
res.status(400)
res.send({ error: err })
return
}
})
}
This is what I get back:
When I look at the req.body for the response it is an empty object even though I can see that state is there when sending the form.
I also tried hardcoding an object and that will show the data on the req.body.
For example if I change the request to
const response = await axios.post('/api/new_invoice', {formData: 'this is form data'})
Then I am able to see formData: 'this is form data' in the req.body
You need to stringify the formData, In your sendInvoice function,
Also can you share the sample request body from postman of you have tested API there
let body= JSON.stringify(formData)
const config = {
headers: {
'Content-Type': 'application/JSON'
}
};
const res = await axios.post('/api/v1/new_invoice', body, config);
To handle an incoming JSON object from HTTP POST Request, you need to write the following code -
var express = require('express');
var app=express();
app.use(express.urlencoded()); // To parse URL-encoded bodies
app.use(express.json()); //To parse JSON bodies
// Note: (*applicable for Express 4.16+ )

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

Node / Express Post request using a function to send data

I am using a function that prevents the default submit of a form and want to use a second function that posts this so i can work / modify the data in the fist function before submitting.
the first function
const Test = document.querySelector('.test')
Test.addEventListener('submit', (e) => {
e.preventDefault()
const username = CreateUser.querySelector('.username').value
const password = CreateUser.querySelector('.password').value
post('/about', { username, password })
})
i found the following the function that submits the Post request. It works fine when the destination is another function without leaving the actual page.
function post (path, data) {
return window.fetch(path, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
}
I use the following routing in my index.js
const express = require('express')
const bodyParser = require('body-parser')
const store = require('./store')
const app = express()
app.use(express.static(__dirname + '/public'))
app.use(bodyParser.json())
var path = require('path')
app.post('/createUser', (req, res) => {
store
.createUser({
username: req.body.username,
password: req.body.password
})
.then(() => res.sendStatus(200))
})
app.get('/about',(req, res) => {
res.sendFile(path.join(__dirname, './public', 'about.html'));
})
app.post('/about',(req, res) => {
res.sendFile(path.join(__dirname, './public', 'about.html'));
})
app.listen(7555, () => {
console.log('Server running on http://localhost:7555')
})
When i make a post to /createUser i works fine and i can insert the data to a mysql table using a function.
I now want to make a post to /about using a function and eventually pass the data.
Why does it not work? I dont get any error.
The about.html, index.html and the js file with my functions are all in the public folder.
thanks for helping
Your route for the post function
app.post('/about',(req, res) => {
res.sendFile(path.join(__dirname, './public', 'about.html'));
})
is just returning the about.html page from your public folder. So there wouldn't be an error, you should just be getting back that HTML after posting to that endpoint with how it is currently configured.
The problem is that you'll only be getting this back as the body of your fetch() request. If you're wanting to see the about.html page, you'll want to actually redirect to http://localhost:7555/about.html. If you want to see the result of your fetch() request, you should be able to see the payload in the Networks tab of your DevTools (or your browser of choice's equivalent).

Categories