Node.js React node-fetch empty body post - node.js

I am trying to do a simple post from Reactjs to a node.js server using node-fetch; however, the body of my request is always empty (I have not been able to come up with any configuration which results in a non-empty body). I have read seemingly every stackOverflow question about this and none solves my predicament, sadly. Here is my reactjs code:
fetch('http://localhost:3000/sayhello/', {headers: new Headers({
'Content-Type': 'application/json'
}), method: 'POST', body: {"nose":"bop"} })
.then(function(res) {
return res.json();
}).then(function(json) {
console.log(json);
});
And my server.js:
...
import BodyParser from 'body-parser';
app.use(BodyParser.urlencoded({extended : true}));
app.use(BodyParser.json());
app.post('/sayhello/', function(req, res) {
console.log(req.body);
res.send(req.body);
});
The console always gives an empty body, and the response is always undefined. This happens too when rather than JSON I just post a string as body. Any ideas?
Thanks

Not to worry friends it seems I have figured it out. I was missing JSON.stringify in body. I hope this helps someone sometime, so they avoid pulling out as much hair as I did :)

Related

React - How to send a cookie along fetch and get it in the backend NodeJS?

I have a project where I set a cookie with universal-cookie.
cookies.set('auth-token', data);
I then have a fetch request:
const getMeals = async (date: Date) => {
let res= await fetch("http://127.0.0.1:5000/meals/", {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
date: date
}),
});
const data = await res.json();
console.log(data);
}
And a backend where it gets checked (NodeJs, ExpressJs):
module.exports = function(req, res, next){
const token = req.header('auth-token');
if(!token){
return res.status(401).json('Access denied!');
}
}
I see the cookie in my mozilla:
But I always get "Access denied!" -> that means the auth-token is not there...
I hardcoded the auth-token into the fetch and it worked.
I checked several websites and almost all stackoverflow posts on this theme. I also checked the fetch-api documentation, but I couldnt come up with a solution...
Both the client and the server are running on localhost.
I hope someone can help me with this topic.
UPDATE
Andreas suggested that I should either set the header(frontend) or look for cookie- instead of header-values(backend).
I decided to do the second approach.
Server.js
var cookieParser = require('cookie-parser')
const usersRouter = require('./routes/users'); //where auth.js gets imported
app.use(cors());
app.use(express.json());
app.use(cookieParser());
app.use('/users', usersRouter);
I tried changing the position of app.use(cookieParser()); to above all others - didnt help.
auth.js
module.exports = function(req, res, next){
const cookie = req.cookies['auth-token'];
console.log(cookie);
}
The problem I now have is that the cookie value is undefined even though the cookie gets displayed in FireFox.
I tried to do the steps of this post, but this doesnt work afterwards I went to their official documentation and found nothing.
I also stumbled upon this one, which makes me think that something is wrong in the frontend...
Frontend-File where I set the cookie:
import Cookies from 'universal-cookie';
const cookies = new Cookies();
const login = async () => {
let res= await fetch("http://127.0.0.1:5000/users/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: (e.target as HTMLFormElement).email.value,
password: (e.target as HTMLFormElement).password.value,
}),
});
const data = await res.json()
if(res.status === 200){
cookies.set('auth-token', data);
setUserId((jwt_decode(data) as any)._id);
navigate("/");
}else{
alert(data);
}
}
Does someone have an idea?
I could fix the problem with the help of a friend. I had to add "proxy": "http://localhost:5000/" to my package.json in my React-Project, because the port is important for the cookie so localhost:5000 and localhost:3000 are not the same for it. I could also remove the app.use(cors()) from my NodeJs-Project, because of it.
I would suggest you run your front end on http://127.0.0.1:3000. If you are already doing that then you have to call fetch with credentials options set to include.
This is because unless fetch() is called with the credentials option set to include, fetch():
won't send cookies in cross-origin requests
won't set any cookies sent back in cross-origin responses
As of August 2018, the default credentials policy changed to same-origin. Firefox was also modified in version 61.0b13)

ajax requests to Node.js

In my app.js file in Node.js I have this:
app.use(express.json());
which I thought was good enough but whenever I submit data via jQuery/Ajax the response is an empty object.
After doing the below however, it now get the data from req.body. But, I thought that in the newer versions of Express it was not necessary to do this anymore?
const bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
The Ajax request:
$.ajax({
url: 'http://localhost:8000/api/v1/endpoint',
method: 'POST',
data: {key: key}
})
.done(function(data) {
console.log(data)
})
.fail(function(data) {
console.log(data);
})
The issue is with how you're making your ajax requests. express.json expects the Content-Type of the request to be JSON and I believe if you check your network call on the browser DevTools you'll see that the Content-Type of your request is not JSON.
You need to set the headers in your ajax request and also send valid JSON data like so
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify({key: key})
Then the express.json middleware will handle the request and you won't need to use the bodyParser lines of code you're using.

NodeJS http post data empty

I am not able to get the data in the http post method of express nodejs.I am posting data from angular2. When i inspect in the network section of chrome, the payload is visible but the same data is received blank at app.post method.Please help me.
angular2 code
this.headers = new Headers();
this.headers.append('Content-Type', 'x-www-form-urlencoded');
let body = JSON.stringify({name:"Lionel Messi"});
return this.http
.post('http://localhost:8081/save',body
,this.headers);
}
nodejs code
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.post('/save', function (req, res) {
console.log("Got a POST request for the homepage");
console.log(req.body);// output - {}
res.send('Hello POST');
})
Network Section in Chrome....payload is proper
alert method in node.js will not work . You need to use console.log("Hello");
Second thing is to get body data , use req.body.name
My way of writing code is like below and it works
$http({
method: 'POST',
url: 'http://localhost:8081/save',
data: {name:"Lionel Messi"}
})
.success(function(data) {
return data
})
.error(function(error) {
// handle error
});
Other way you can try is:
$http.post('http://localhost:8081/save', {name:"Lionel Messi"})
.then(function(data) {return data})
.catch(function() {console.log("Error Occured");});
You can do it like this-
Suppose you have sent username and password from your browser by post method.
app.post("/ url,function(request,response)
{ var username=request.body.username;
var password=request.body.password;})

empty body on resource.$save

So I've tried the suggestions from
AngularJS POSTs empty requests?
AngularJS $resource RESTful example
Send Request Body on $resource
But I'm still getting an empty req.body
I can do a get just fine and even pass an id for the get. But I can't seem to POST and transfer the data to the server.
Controller:
.controller("createEventController", ["$scope", 'CreateEventService', '$location', function($scope, CreateEventService, $location){
$scope.event = {};
$scope.submitEvent = function(){
console.log($scope.event);
var events = new CreateEventService($scope.event);
console.log(events);
events.save(function(response){
console.log(response);
}, function(error){
console.log(error);
});
}
}])
Service
factory('CreateEventService', function($resource){
return $resource('api/createEvent');
});
Change events.save(...) to events.$save(...)
You should use bodyParser.json(). The $resource, by default sends his requests with the header "Content-Type": "application/json;charset=UTF-8" and without bodyParser.json() you're API is not able to deal with the request content.
if using express 4.1.2, despite it fussing about bodyParser() being deprecated, having
app.use(bodyParser.urlencoded({
extended: true
}));
was for some reason, giving me an empty body. For whatever reason, not having urlencoded crashed my server before (old express version I think). Just change it back to (using express 4.1.2)
app.use(bodyParser());
and fixed. I also removed the methodOverride() as that was causing my server to hang. If anyone knows a more correct approach, I would appreciate it.

expressJS request object

I'm trying to go through the expressJS tutorial. This is my server code:
var express = require('express');
var app = require('express').createServer();
app.use(express.bodyParser());
app.post('/', function(request, response) {
console.log('Inside the post request!');
console.log(request);
response.send(resquest.body);
});
app.listen(3000);
and here is the POST request I am simulating:
$.ajax({
url: 'http://localhost:3000',
type: 'POST',
datatype: 'json',
data: {hello: 1},
success: function () {
console.log('Success!');
},
error: function () {
console.log('Error!');
}
});
The problem is that the request object does not seem to contain data: {hello: 1}. Instead it is a big mess of under-the-hood parameters. Am I doing something stupid?
I think that since you're not setting the content type to multipart/form-data it's assuming form encoded data. In which case, you'd set your data in your ajax request to be:
data: 'hello=1'
Set your content-type to: application/x-www-form-urlencoded
Access it via request.body.hello. It's been awhile, but try that.
You've written resquest.body instead of request.body; when you fix that, you'll be able to use request.body.data as others have pointed out.
You need to look at request.body. When you do request.body, you get {hello: 1}.

Resources