Why REQ.BODY is always empty? - node.js

I know there are a lot of answer already marked as a working solution, but I can't make it work in my case, so please don't marked it as already answered, this is my scenario:
AJAX CLIENT SIDE
var data ={};
data.test="ciaozio";
$.ajax({
url: 'http://localhost:5000/dir',
method: "POST",
contentType: "application/json",
data: JSON.stringify(data),
header: "Access-Control-Allow-Origin",
success: function(data){
console.log(data);
},
error: function(data) {
console.log("error");
}
});
NODEJS SERVER-SIDE
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var router = express.Router();
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.use(bodyParser.json()); // support json encoded bodies
app.use('/', router);
app.post('/dir', function (req, res) {
console.log(req.body);
res.end("Ok");
})
var server = app.listen(5000, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
CONSOLE-OUTPUT
Example app listening at http://:::5000
{}
CLIENT-SIDE CONSOLE OUTPUT
Access to XMLHttpRequest at 'http://localhost:5000/dir' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
index.js:29 error
jquery-3.4.1.min.js:2 POST http://localhost:5000/dir net::ERR_FAILED

You need to add and configure CORS to your request.
Steps:
1.Install cors npm package
npm install cors
2.Node server-side snippt
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
//app.use(...) lines;
// app.post(..) lines;

Related

node express website with REST authentication API - CORS problem

I am new to nodejs + Express but I'm trying to build a very quick proof of concept website which allows user to authenticate via a REST API.
I have come against a CORS problem and despite installing the cors module and using it as suggested in the documentation, I am still getting the following error:
Access to XMLHttpRequest at xxx has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: The
'Access-Control-Allow-Origin' header has a value
'https://www.example.com' that is not equal to the supplied origin.
Here is my (simplified) code:
app.js
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const cors = require('cors');
compression = require('compression'),
shouldCompress = (req, res) => {
if (req.headers['x-no-compression']) {
// don't compress responses if this request header is present
return false;
}
// fallback to standard compression
return compression.filter(req, res);
};
const app = express();
// EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
// Parsing related
app.use(express.urlencoded( { extended: false })); //Parse URL-encoded bodies
app.use(express.json()); //Used to parse JSON bodies
app.use(compression({
filter:shouldCompress,
threshold: 3
}));
app.use(express.static('public'));
app.disable('x-powered-by');
// Using the flash middleware provided by connect-flash to store messages in session
// and displaying in templates
const flash = require('connect-flash');
app.use(flash());
// Sessions
const session = require('express-session');
app.use(session({
secret: 'fat cat 42',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
// Initialize Passport and restore authentication state, if any, from the session.
const passport = require('passport');
require ('./config/passport')(passport);
app.use(passport.initialize());
app.use(passport.session())
// Routes
app.use('/', require('./routes/index'));
app.use('/member', require('./routes/users'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on port: ${PORT}`));
users.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
require ('../config/passport')(passport);
router.post('/signin', passport.authenticate('facebook', {
successRedirect : '/home',
failureRedirect : '/'
}));
module.exports = router;
Here is the script portion of the view that makes the AJAX POST
homepage.ejs
$(document).ready(function(){
$('#demo').click(function(e){
$.ajax({
method: "POST",
url: "/member/signin",
data: {
"source": $(this).attr('id')
},
dataType: "json",
timeout: 5000 // 5000ms
}).done(function(data) {
// is called if request is successful
console.log('Success:' + data);
}).fail(function(jqXHR, status) {
// is called if request fails or timeout is reached
alert('Request could not complete: ' + status);
});
});
});
How do I fix this so that the AJAX calls work?
essentially you need to permit cross-site origin requests. you do that by setting the access-control-headers normally with some proxy like nginx in front of your node server like the following (it is not recommended to have node directly exposed on port 80)
#nginx config
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, HEAD, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With';
return 204;
}
if you have expressjs you could use this cors middleware
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.post('/signin/', function (req, res, next) {
// ....
})

NodeJs unable catch the data post from ReactJs form

I using ReactJs build the form for user key in the details. I also using NodeJs to handle the post data from the React. But the NodeJs seem like did not catched the data.
This is react event handling
handleSave(e){
let caseData=this.state.caseInfo
let url = 'http://localhost:8080'
console.log(caseData)
fetch(url,{
method:"POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
data: JSON.stringify({caseInfo: caseData}),
})
}
This is NodeJS
var http = require('http');
var url = require('url');
var bodyParser = require('body-parser')
var express = require('express')
var app = express()
http.createServer(function(req,res){
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
app.use(function (req, res){
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
console.log(JSON.stringify(req.body));
})
}).listen(8080);
I expect the data from the React can using post method to the Node and display the data in console log. However in the console of the server it display nothing.
It seems like you're not using express in the standard way. I'd change it to be more like the following...
app.use(bodyParser.json());
app.post('/', (req, res) => {
res.json({ posted: req.body });
console.log(JSON.stringify(req.body));
});
app.listen(8080);
And probably just get rid of the call to http.createServer altogether.
--
Check out the docs for more routing examples: https://expressjs.com/en/starter/basic-routing.html
If you are serving your react app from another server, for instance localhost:3000 (as used by create react app), and you are trying to make api calls to a server on localhost:8080 you are going to get CORS errors because the browser sees these as two different domains. To get started, you can look at the docs here: https://expressjs.com/en/resources/middleware/cors.html
But you will probably have to npm install cors where your server lives and use something like the following:
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.use(bodyParser.json());
app.post('/', (req, res) => {
res.json({ posted: req.body });
console.log(JSON.stringify(req.body));
});
app.listen(8080);

ExpressJs request body is empty

I have an express app at localhost:5000 and a react app at localhost:3000.
I am calling it via
fetch(`${backendUrl}/charge`, {
method: "POST",
mode: "no-cors",
headers: {
"Content-Type": "application/json"
},
body: {
stripeToken: token,
chargeAmount: this.state.donationAmount
}
})
And responding with
function route(req, res) {
console.log(req.body);
}
Server should be properly configured to work with CORS, but the body is still empty.
//configure env variables
require("dotenv").config();
//import packages
var express = require("express");
var bodyParser = require("body-parser");
var cors = require("cors");
//import route functions
const StripeRoute = require("./StripeRoute");
//setup app
const app = express();
const port = process.env.PORT || 5000;
//setup bodyparser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//Setup CORS
app.use(cors());
app.options("*", cors()); // include before other routes
//Connect functions to API routes
app.post("/charge", StripeRoute);
module.exports = app;
According to the documentation, the body option should be one of a few specific types, Object not being one of them.
Try using a JSON string:
body: JSON.stringify({
stripeToken: token,
chargeAmount: this.state.donationAmount
})
EDIT: because you're using no-cors, you can't set Content-Type application/json. Instead, you need to generate a URL-encoded string and set Content-Type to application/x-www-form-urlencoded (because no-cors will only work using "simple headers", as explained here and further).

BodyParser data is undefined after AJAX call

The body parser body is {}. I've already done research and made sure that my ajax data key is set correctly as well as make sure the middleware is set up correctly as well. Here is my frontend ajax call
$.ajax({
type:"GET",
url:"/api",
data: {course:"MATH-226"},
success: function(data){ alert(data);}
});
And here is my backend server.js file:
'use strict'
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const alg = require('./app/algorithm.js');
const app = express();
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.get('/api', (req, res) => {
console.log(req.body);
alg.create(req.body.course, answer => res.send(answer));
});
let server = app.listen(3000, () => {
let host = server.address().address;
let port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
You are using a GET request, so it's probably not being sent. If you need to send something, you can attach it as a header or include it in the query string of the url. If you want to send data, I would use a POST request.
Check out this article
How to send data in request body with a GET when using jQuery $.ajax()

Express POST request.body undefined

I am trying to make POST work with Express (4.13.3 version). when I print request.body.user, it says 'undefined'. I am using Chrome Poster to post my JSON request. Here is how my request looks
{
"user":"testUser",
"password":"test pwd"
}
the URL I use: http://localhost:4000/first
and my server.js file.
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/first', function (request, response) {
console.log('FIRST POST hello world');
console.log('req.body:' + request);
var user_name=request.body.user;
var password=request.body.password;
console.log("User name = "+user_name+", password is "+password);
response.end("yes");
});
var server = app.listen(4000, function() {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
when I post the request, here is what I see on my Node console.
Example app listening at http://:::4000
FIRST POST hello world
req.body:[object Object]
User name = undefined, password is undefined
Why I am not able to get my 'user' and 'password' values here from my request? I am getting 'undefined' for both of these variables.
try this:
app.use(bodyParser());
if this still doesn't work change your request to this:
user=testUser&password=test+pwd
This is how the request body have to look using Chrome's "Advanced REST Client".

Resources