fetch() POST request to Express.js generates empty body {} - javascript

Goal: send some defined string data from HTML in a fetch() function e.g. "MY DATA"
My code:
HTML
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
function fetcher() {
fetch('/compute',
{
method: "POST",
body: "MY DATA",
headers: {
"Content-Type": "application/json"
}
}
)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
}
</script>
</body>
</html>
Server.js
var express = require("express");
var app = express();
var compute = require("./compute");
var bodyParser = require("body-parser");
//not sure what "extended: false" is for
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/compute', (req, res, next) => {
console.log(req.body);
var result = compute.myfunction(req.body);
res.status(200).json(result);
});
Currently: console.log(req.body) logs {}
Desired: console.log(req.body) logs "MY DATA"
NOTES:
I also tried sending body in fetch() as body: JSON.stringify({"Data": "MY DATA"}) but get the same empty {}
I either my fetch() request, or my bodyParser(), is not setup correctly.

Add the following line in addition to your current bodyParser app.use() right before:
app.use(bodyParser.json());
This will enable bodyParser to parse content type of application/json.
Hopefully that helps!

I feel a bit stupid now once I worked out what bodyParser.urlencoded (source: https://www.npmjs.com/package/body-parser#bodyparserurlencodedoptions)
Returns middleware that only parses urlencoded bodies
Solution
Changed the fetch() request, from:
body: "MY DATA",
headers: { "Content-Type": "application/json" }
to
body: JSON.stringify({"Data": "MY DATA"}),
headers: { "Content-Type": "application/x-www-form-urlencoded" }
which solved the problem! Console logged:
{ '{"Data":"MY DATA"}': '' }

Related

app.use(express.raw()) not working in Express.js

I am making an Express application that takes in (binary) post data. Here is my code below.
Server-side:
var express = require('express');
var app = express();
var PORT = 3000;
app.use(express.raw());
app.post('/', function(req, res) {
console.log(req.body);
res.end();
});
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
app.listen(PORT, function() {
console.log("Server listening on port", PORT);
});
index.html:
<script>
fetch("/", {
method: "POST",
body: "hello world",
});
</script>
However, when I run this code, when logging the request body, it logs an empty object. And when I looked at the documentation, it says that the request body will be an empty object if there was no body to parse. But I had a body in the request. What am I doing wrong here?
express.raw() only works if you set your Content-Type header in your fetch to `application/octet stream. So your new fetch method would look like this.
fetch("/", {
method: "POST",
body: "hello world",
headers: {
"Content-Type": "application/octet-stream"
}
});
But what if you don't want the content type to be application/octet-stream? In this case, you can specify in the express.raw() options that the content type to parse the body can be any type. How to do this? Replace this:
app.use(express.raw());
With this:
app.use(express.raw({type: '*/*'}));
The type option is the needed content type for body-parser to parse the body, and the */* means that any content type will be accepted.
For express.raw() to parse, add "Content-Type": "application/octet-stream" inside headers in your fetch(). Like so:
fetch("/", {
method: "POST",
body: "hello world",
headers: {
"Content-Type": "application/octet-stream",
},
});
Use this for your usecase
app.use(express.text());

Express js request body is not excatcly i want

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'

React, axios, content-type

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

Post request with node js

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

body data not sent in axios request

I am trying to send data through axios request to my backend script, but the body looks empty.
Here's a request sent from front-end:
axios.request({
method: 'GET',
url: `http://localhost:4444/next/api`,
headers: {
'Authorization': token
},
data: {
next_swastik: 'lets add something here'
},
}).then((res)=>{
console.log("api call sucessfull",res);
}).catch((err)=>{
console.log("api call unsucessfull",err);
this.props.toggleLoading(false);
})
Here's a back-end:
app.get('/next/api', verifyToken, function(req, res) {
console.log(req.body);
})
But I am getting {} empty body. I am getting headers and other data but not data.
GET requests should not have a body.
Change the method from 'GET' to 'POST'
Like so:
axios.request({
method: 'POST',
url: `http://localhost:4444/next/api`,
headers: {
'Authorization': token
},
data: {
next_swastik: 'lets add something here'
},
})
and change your api to expect a post
app.post('/next/api', verifyToken, function(req, res) {
console.log(req.body);
});
or
Change the data property to params
axios.request({
method: 'GET',
url: `http://localhost:4444/next/api`,
headers: {
'Authorization': token
},
params: {
next_swastik: 'lets add something here'
},
})
and change the api to log out the params
app.get('/next/api', verifyToken, function(req, res) {
console.log(req.params);
});
and like #MaieonBrix said, make sure that your headers contain the content type that you are sending.
It looks like you only have two points left to make it work :
one : the http method should be set to POST instead of GET since you want to send something.
two : you can then add the http header (like what you did with the authorization header) Content-Type: 'application/json`
On the back-end don't forget to use some kind of body parser utility package like this one : body-parser and set it up with your app.
I suppose your server is using express, here is how you will do it with express :
const express = require('express');
const app = express();
const bodyParser = require('body-parser')
const jsonParser = bodyParser.json();
app.use(jsonParser); // use it globally
app.get('your_route', jsonParser, otherMiddleware, (req, res) => ...); // use it for specific routes
/* ... rest of your code */
If you get an error that "bodyParser is deprecated", try this -
app.use(express.json()); //To parse JSON bodies (Applicable for Express 4.16+)
And use "post" method, if you want to get data from body of the HTTP request.
Try this
this.axios('realties', { params: this.filter })

Categories

Resources