Im working on simple app that allows you to register new user. I managed to create fetch POST request and catch it with express app.post method. It works but the value that req.body is retruning is not plain object but something more that I want.
It's literally returning something like this : { '{"login":"fff","password":"sss"}': '' }
But I want it to be just sth like this: {"login":"fff","password":"sss"}
Here is my client side code
function eventListener() {
const formSubmit = document.querySelector('.register-form');
const newUser = new Register();
formSubmit.addEventListener('submit', (e) => {
e.preventDefault();
newUser.checkInputs();
const form = e.target;
const formData = new FormData(form)
const userData = {
login: formData.get('login'),
password: formData.get('password'),
}
console.log(userData);
fetch('/register', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: JSON.stringify(userData)
})
.then(response => {
console.log(response);
})
})
}
document.addEventListener('DOMContentLoaded', eventListener)
And here is server code
const express = require('express');
const path = require('path');
const app = express();
app.use(express.json())
app.use(express.urlencoded({
extended: true
}))
app.use(express.static('static'))
app.post('/register', (req, res) => {
console.log('ok');
console.log(req.body);
res.end();
})
app.listen(process.env.PORT || 5000, () => {
console.log('running...');
})
Don't lie to the server:
'Content-Type': 'application/x-www-form-urlencoded'
You are sending JSON.
By telling the server you are NOT sending JSON, you are confusing it.
It is trying to parse it as application/x-www-form-urlencoded
Tell it you are sending JSON:
'Content-Type': 'application/json'
Related
I want to send values from react to node. I am using fetch but I am not getting. Here's the code:
React Code:
const values = {email,pass}
const data = {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(values),
}
fetch('http://localhost:8000/', data)
.then(res => res.json())
.then(data => console.log(data))
Node Code:
const express = require("express")
const cors = require('cors')
const app = express()
app.use(
cors({
origin: '*'
})
)
app.listen(8000, 'localhost')
app.post('/' , ( req, res ) => {
console.log(req.body)
} )
When I am visiting to this http://localhost:8000/
i am getting an error
Cannot GET /
use json body parser:
app.use(express.json());
You need express to use json body parser:
app.use(express.json());
Additionally you are not sending any response from your Node Server to the client,
try something like this this:
app.post('/' , ( req, res ) => {
console.log(req.body)
const data = JSON.stringify(req.body)
console.log(data)
res.status(200).json({data: data});
})
MRE -> node-server : react app
When I send a POST request using Postman, I get the expected result. This is the request that I am sending using Postman
and test sent gets printed to the console of my node server
If I send a request from my react form however, test sent does not print to the console, but the catch block of my fetch request get's executed and err is printed to the console of my react app, followed by {}.
I would like to know why my POST request is not working and is not getting received by the server
Below is the function that I call when someone clicks the submission button of my form created in react
Function called on form submission
nodeUrl = 'https://localhost:6060?'
const submitData = async () => {
fetch(nodeUrl, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({'test': 'test'})
}).then((res) => {
alert('then')
}).catch((err) => {
alert('err')
alert(JSON.stringify(err))
})
}
}
This is the server that I run using node server.js
server.js
server.post('/', function(req, res) {
console.log('test sent')
mailer.messages().send(req.body)
.then((mes) => {
console.log(mes)
res.json({ message: 'Thanks for your message. Our service team has been notified and will get back to you shortly.' })
}).catch(err => {
console.log(err)
res.json(err);
})
});
The majour issue here is due to CORS. CORS support can be used to overcome this. Just keep in mind to have this only for development mode(see below codes).
But, as per the Postman's snapshot and provided GitHub repositories, the request from Front-end should be of multipart/form-data type. Thus, the Front-end code would look like this
const nodeUrl = "http://localhost:6060/";
const submitData = async () => {
// create a FormData object
const formData = new FormData();
formData.append('form', 'example#email.com');
formData.append('to', 'example#email.com');
// this auto adds 'multipart/form-data' + HASH header in the request
fetch(nodeUrl, {
method: "POST",
body: formData
})
.then(res => {
console.log(res);
}).catch(err => {
console.log('Error -', err);
});
};
To handle multipart/form-data request in the ExpressJS, you need a plugin Multer.
const express = require('express');
const bodyParser = require('body-parser');
const multer = require('multer'); // for 'multipart' type request
const server = express();
const upload = multer();
// allow CORS requests in development mode
if (process.env.NODE_ENV === 'development') {
// Server run command - "NODE_ENV=development node server.js"
const cors = require('cors');
server.use(cors());
}
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({extended: true}));
// using Multer middleware form extracting 'FormData' payload
server.post('/', upload.none(), function(req, res) {
console.log('Received body', req.body);
... // other codes
});
Strategy 2(plain JSON) -
If that 'multipart/form-data' strategy was unintentional and you just want to send simple JSON, use below codes -
In Front-end, trigger API request as -
fetch(nodeUrl, {
method: "POST",
headers: {
'Content-Type': 'application/json', // this needs to be defined
},
body: JSON.stringify({ from: 'some#email.com', to: 'other#email.com' })
})
In server, just ignore codes related to Multer and only keep your API as -
server.post('/', function(req, res) {
console.log('Received body', req.body);
... // other codes
});
I ended up using a better fetch request, which was put together for me by selecting code -> Javascript Fetch in Postman(under the save button)
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("from", "example#email.com");
urlencoded.append("test", "test");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
};
fetch("http:localhost:6060/, requestOptions)
.then(response => {
if (response.ok){
response.json().then(json => {
console.log(json)
})
}
})
.catch(error => console.log('error: ', error))
I am using fetch to post data from react side to nodejs (both of which are running in my localhost) so what i am doing is
let formData = new FormData();
formData.append("agent_name", this.state.agentName);
formData.append("agent_email", this.state.agentEmail);
formData.append("agent_phone", this.state.agentPhone);
formData.append("agent_id", this.state.agentID);
formData.append("agent_password", this.state.agentPassword);
formData.append("state", this.state.selectedState);
formData.append("city", this.state.selectedCity);
formData.append("file", this.state.file);
formData.append("imageurl", this.state.imageUrl);
fetch("http://localhost:4000/add_delivery_agent", {
method: "POST",
body: formData,
})
.then((response) => response.json())
.then((responsejson) => {
console.log(responsejson);
});
and then on server side i did
exports.addDeliveryAgent = async (req, res, next) => {
let data = req.body;
console.log(data);
}
};
but console.log(data) gives me empty object always, what am i doing wrong here ?
Also the data gets posted via axios but i want it via fetch !
App.js config is
const express = require("express");
const bodyparser = require("body-parser");
const app = express();
const mongoconnect = require("./utils/database").mongoconnect;
const path = require("path");
var cors = require("cors");
// const adminUserRoute = require("./routes/admin/user/user.js");
const adminDeliveryAgentRoute = require("./routes/admin/deliveryAgent/deliveryAgent");
const user = require("./routes/admin/user/user.js");
app.use(express.urlencoded());
app.use(bodyparser.urlencoded({ extended: false }));
app.use(bodyparser.json());
app.use(cors());
app.use("/tfd/controlcenter/", express.static(path.join(__dirname, "/build")));
// app.use(adminUserRoute);
app.use(adminDeliveryAgentRoute);
app.use(user);
mongoconnect(() => {
app.listen(4000, () => {
console.log("running 4000");
});
});
try adding Content-Type header
fetch("http://localhost:4000/add_delivery_agent", {
method: "POST",
body: formData,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
// or
// 'Content-Type': multipart/form-data
},
})
Don't use form data instead use plain object as bodyparser doesn't support multipart/form-data which is what form data uses
formData={}
formData.agent_name=this.state.agentName;
formData.agent_email=this.state.agentEmail;
//..
formData.imageurl=this.state.imageUrl;
fetch("http://localhost:4000/add_delivery_agent", {
method: "POST",
body: formData,
})
.then((response) => response.json())
.then((responsejson) => {
console.log(responsejson);
});
I have already searched a lot, but none of the solutions found work: Cannot send content-type by axios. but if I use the postman interceptor and I 'send' the request generated by axios this time it works: the node.js / express server correctly receives the request and body-parser works normally!
React side:
const API_URL = "http://localhost:8800/auth/";
const headers = {
accept: 'application/json, text/plain, */*',
'content-type': 'application/json;charset=UTF-8'
};
class AuthService {
register(pseudo, email, password) {
return axios.post(API_URL + "signup/",
{ pseudo, email, password },
{ headers: headers})
.then(response => {
if (response.data.accessToken) {
localStorage.setItem("user", JSON.stringify(response.data));
}
return response.data;
});
}
server side
const app = express();
app.use(function (req, res, next) {
console.log( req.headers);
next();
});
app.use( bodyParser.urlencoded({ extended: true }), bodyParser.json());
Usually when I use axios I send the headers in a config variable like this and I stringify the body so it sends as JSON object and not a JS object.
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const body = JSON.stringify({arguments});
try {
const res = await axios.post(/url, body, config);
...
Here's a link to the docs for a little more reading about it:
https://github.com/axios/axios
I'm trying to make a post request with node.js and when I try to run it, I get the data to show up in the console but noot the body of my HTML. In the console I get the error
app.js:4 POST http://localhost:8000/addAnimal net::ERR_EMPTY_RESPONSE
postData # app.js:4
(anonymous) # app.js:25
app.js:21 Uncaught (in promise) TypeError: Failed to fetch
It seems like the function is working but not the actual post request part. I can't for the life of me figure out what I'm doing wrong.
This is my code:
server.js:
projectData = {};
/* Express to run server and routes */
const express = require('express');
/* Start up an instance of app */
const app = express();
/* Dependencies */
const bodyParser = require('body-parser')
/* Middleware*/
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const cors = require('cors');
app.use(cors());
/* Initialize the main project folder*/
app.use(express.static('project1'));
const port = 8000;
/* Spin up the server*/
const server = app.listen(port, listening);
function listening(){
// console.log(server);
console.log(`running on localhost: ${port}`);
};
// GET route
app.get('/all', sendData);
function sendData (request, response) {
response.send(projectData);
};
// POST route
app.post('/add', callBack);
function callBack(req,res){
res.send('POST received');
}
// POST an animal
const data = [];
// TODO-Call Function
app.route('/addAnimal')
.get(function (req, res) {
res.sendFile('index.html', {root: 'project1'})
})
.post(function (req, res) {
data.push(req.body)
})
app.js
/* Function to POST data */
const postData = async ( url = '', data = {})=>{
console.log(data);
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data), // body data type must match "Content-Type" header
});
try {
const newData = await response.json()
// console.log(newData);
return newData.json()
}catch(error) {
console.log("error", error)
// appropriately handle the error
};
};
// TODO-Call Function
postData('/addAnimal', {animal:'lion'});
Any help would be greatly appreciated.
Thanks,
Mike
💡 The only one reason why you got message like it, it's because you never send response to the client.
👨🏫 So, You should to send response to the client. For an example, you can look at this code below: 👇
app.route('/addAnimal')
.get(function (req, res) {
res.sendFile('index.html', {root: 'project1'})
})
.post(function (req, res) {
data.push(req.body);
// send data to client
// you can change req.body with the object what you want to sent do the client
res.status(200).send(req.body);
})
📤 Update: Addtional information
Make sure you call the endpoint: http://localhost:8000/addAnimal.
Frontend: Make sure your code like this code below
const postData = async ( url = '', data = {})=>{
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data), // body data type must match "Content-Type" header
});
try {
console.log(await response.json());
return await response.json()
}catch(error) {
console.log("error", error);
};
};
I hope it can help you 🙏.
Try this:
app.route('/addAnimal')
.get(function (req, res) {
res.sendFile('index.html', {root: 'project1'})
})
.post(function (req, res) {
data.push(req.body);
res.send('done'); // send response
});
Change the app.js code with the below.
/* Function to POST data */
const postData = async (url = "", data = {}) => {
const response = await fetch(url, {
method: "POST", // *GET, POST, PUT, DELETE, etc.
credentials: "same-origin", // include, *same-origin, omit
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
try {
return response.json();
} catch (error) {
console.log("error", error);
// appropriately handle the error
}
};
// TODO-Call Function
(async function(){
let res = await postData("/addAnimal", { animal: "lion" });
console.log(res);
})();
And also change the post method like below.
app.route('/addAnimal')
.get(function (req, res) {
res.sendFile('index.html', {root: 'project1'})
})
.post(function (req, res) {
data.push(req.body);
res.status(200).send(data);
})