body-parser does not work, req.body is undefined [duplicate] - express

I can't seem to recover the form-data of a post request sent to my Node.js server. I've put below the server code and the post request (sent using postman in chrome):
Post request
POST /api/login HTTP/1.1
Host: localhost:8080
Cache-Control: no-cache
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="userName"
jem
----WebKitFormBoundaryE19zNvXGzXaLvS5C
NodeJS server code
var express = require('express'); // call express
var app = express(); // define our app using express
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(bodyParser());
app.all('/*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type,accept,access_token,X-Requested-With');
next();
});
var port = process.env.PORT || 8080; // set our port
var router = express.Router(); // get an instance of the express Router
router.get('/', function(req, res) {
res.json({ message: 'I am groot!' });
});
// Login
router.route('/login')
.post(function(req, res){
console.log('Auth request recieved');
// Get the user name
var user = req.body.userName;
var aToken = getToken(user);
res.json({
'token':'a_token'
});
});
app.use('/api', router);
app.listen(port);
The login method tries to obtain the req.body.userName, however, req.body is always empty.
I've seen other cases on SO describing such behavior but none of the related answers did apply here.
Thanks for helping out.

In general, an express app needs to specify the appropriate body-parser middleware in order for req.body to contain the body.
[EDITED]
If you required parsing of url-encoded (non-multipart) form data, as well as JSON, try adding:
// Put this statement near the top of your module
var bodyParser = require('body-parser');
// Put these statements before you define any routes.
app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
First, you'll need to add body-parser to the dependencies property of your package.json, and then perform a npm update.
To handle multi-part form data, the bodyParser.urlencoded() body parser will not work. See the suggested modules here for parsing multipart bodies.

I followed this
https://www.tutorialspoint.com/expressjs/expressjs_form_data.htm
var bodyParser = require('body-parser');
var multer = require('multer');
var forms = multer();
// apply them
app.use(bodyParser.json());
app.use(forms.array());
app.use(bodyParser.urlencoded({ extended: true }));
// how to use
router.post('/', function(req, res) {
console.log(req.body);
console.log('received the widget request');
});

To handle multipart/form-data request that support file upload, you need to use multer module. npm link for multer middleware

For Json: Use body-parser.
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))
(you should Also send Content-Type: application/json in request header)
For Normal Form, Or multipart form (form with files), Use body-parser + multer.
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))
app.use(multer().array())
(You should NOT send Content-Type: application/json in this case. you should send nothing, or Content-Type: multipart/form-data if you have files in form.
in postman you should not send Content-Type: multipart/form-data manually. otherwise you'll get an error (Boundary not found). (it will add this automatically.).)

Make sure to put in this order:
bodyParser.json() first.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

Make sure you are not sing enctype as multipart/form-data, body parser does not support it.
use below line before you define any route.
app.use(bodyParser.urlencoded());
app.use(bodyParser.json());

Related

CORS 400 Bad Request with fetch, express server

I'm trying to send a POST request from 127.0.0.1:8080 to my express server in localhost:3000/trips
I'm having a lot of problem with the cors configuration
First, this is my method to do the POST request
async modifyTrip() {
let json = {
data: "test",
mezzo: "test",
coordinate: ["test"],
tappe: ["test"],
};
let modifyform = document.getElementById("add-form");
modifyform.onsubmit = async (e) => {
e.preventDefault();
await fetch("http://localhost:3000/trips", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: json,
});
};
}
On the server side if I put cors options at that point returns me that error:
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(
cors({
"Access-Control-Allow-Origin": "*",
"Allow-Methods": "GET, POST, DELETE, FETCH",
})
);
app.use("/user", userRoutes);
app.use("/trips", tripsRoutes);
If I try to change the position the error is different my it always gives me problem
app.use(
cors({
"Access-Control-Allow-Origin": "*",
"Allow-Methods": "GET, POST, DELETE, FETCH",
})
);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use("/user", userRoutes);
app.use("/trips", tripsRoutes);
I don't think the matter is of where I put it, but I can't fix this problem anyway. Maybe I have to change some headers in my client side, but i really can't figure it out
Thank you.
It's a 400 Bad Request error, so look up what that means:
The HyperText Transfer Protocol (HTTP) 400 Bad Request response status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (for example, malformed request syntax, invalid request message framing, or deceptive request routing).
So something is wrong with the request and the server is complaining (before it gets to the bit of code which would add the CORS response headers). The CORS error is a side-effect, not the main problem.
If you look at the Network tab of your browser's developer tools, you will be able to examine the request.
The body will look something like this:
[object Object]
Now, you said (using a Content-Type header) you were POSTing JSON, but [object Object] is not JSON (or even a usable representation of your data).
You need to pass JSON to body and not an object. Since you are passing an object, it gets stringified using the default JS mechanism (which gives "[object Object]").
Use JSON.stringify(your_object) to convert it to JSON.

How to save cookie on development localhost

I have node.js with express backend with some endpoints, all works fine testing with curl or postman, but on my client-side with angular on the http.post request i get the response correctly, but no cookie is saved.
I've tried changing my localhost dns, after some try i'm ended up using 127.0.0.1:4200 client and 127.0.0.1:3000 backend.
backend code:
const express = require('express');
const bodyParser = require('body-parser');
const webpush = require('web-push');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(cookieParser());
app.post(path, /*here I call my function*/);
[...]
/*in my function i set cookie with these lines*/
res.cookie('userData',
{token: token,},{ httpOnly: true, secure: false }
);
client code:
[...]
constructor(private http: HttpClient) {}
[...]
/*request on my button click*/
this.http
.post<AuthResponse>(path, bodyReq)
who cares about these pieces of code, lets see the result.
in the response header i can see the set-cookie, and when i switch to the cookie tab of the request i can see it correctly, but..
something is telling chrome to don't save my cookie, he received it!!
I've already check on web about cors, domains, cookie settings.
Nothing works for me.
Thanks for any help.
the BENARD Patrick tips was right!!
To solve my problem add withCredentials both on client and server (using this solution I've had to specify the domain)
client code:
return this.http
.get<AuthResponse>(path, {
withCredentials: true,
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'www.dns_to_127.0.0.1.com:4200',
}),
})
server code:
app.use(
cors({
origin: 'http://www.dns_to_127.0.0.1.com:4200',
credentials: true,
})
);
credentials: Configures the Access-Control-Allow-Credentials CORS header. Set to true to pass the header

How to retrieve form-data values in Express js?

I created a form data in Postman and send a http post request. but when I send the request, it shows there is no form data in the destination!
here is my codes in backend :
app.js file:
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var routesImagesApi = require('./api/routes/imagesrouters');
app.use('/api/images', routesImagesApi);
api/routes/imagesrouters.js file:
var router = express.Router();
var ctrlAuth = require('../controllers/images');
router.post('/imageUpload', ctrlAuth.imageUpload);
controllers/images.js file:
module.exports.imageUpload = function (req, res) {
res.status(200);
res.json({"Returned data":req.body});
}
I created a request in postman with two key-value form-data body.
here is my request:
POST > http://localhost:3000/api/images/imageUpload
and form-data body key-values are these :
key:name , value:Sarah
key:family , value:Thomas
Below image is Postman screenshot :
I expected postman show me the form-data key values but as you can see it shows nothing!
{
"Returned data": {}
}
Do you have any idea?
Please use the multer package or you could write a custom handler for making express handle multi part form data i.e "files/imgs..etc "
multer package
and
writing your own custom handler
p.s this could be a duplicate issue

How to solve CORS policy issue in a fullstack app [duplicate]

This question already has an answer here:
CORS Error: “requests are only supported for protocol schemes: http…” etc
(1 answer)
Closed 3 years ago.
I am building a MEVN-stack app, but I fail to make a request from my fron-end to the server due to Cross origin policies. I have enabled the cors middleware for all routes, but it does not take effect. I also tried applying it on each route individually and to specify the origin, but still no effect.
index.js:
const express = require('express')
const cors = require('cors')
const mongoose = require('mongoose')
const BanksController = require('./controllers/BanksController')
const OfficesController = require('./controllers/OfficesController')
const PORT = process.env.PORT || 3000
mongoose.connect(process.env.DB, { useNewUrlParser: true, useUnifiedTopology: true });
const app = express()
app.use(cors({ origin: 'http://localhost:3001' }))
app.get('/api/banks', BanksController.index)
app.get('/api/offices', OfficesController.index)
app.listen(PORT, () => console.log('Listening on port ' + PORT))
the ajax request:
axios.get('localhost:3000/api/banks')
.then(res => console.log(res))
.catch(err => console.log(err))
Try changing this:
axios.get('localhost:3000/api/banks')
to this:
axios.get('http://localhost:3000/api/banks')
Notice how the error message complains about the protocol scheme.
The problem is not your server. The problem is that using localhost:3000 treats localhost: as a scheme. The 'scheme' is the bit of the URL before the first colon.
You won't even see the request in the Network section of the developer tools because the browser doesn't know how to make a localhost: 'request'.
Try to add:
app.use(cors({ origin: 'http://localhost:3001/*' }))
It will be enabled for all routes. Or just use:
app.use(cors())
app.options('*', cors());

Recreate a post request in postman

I have the following javascript code, to produce a post request.
var postUrl = "http://localhost:3100/radiance";
xhttp.open("POST", postUrl, true);
xhttp.setRequestHeader('Content-type', 'application/json');
let radFile = {"radfile":"long string"}
let solarJson = {"key1":"value1","key2":"value2"}
let latitude = 45
let longitude = 24
msgJson=JSON.stringify({'radFile':radFile,'speedSolar':solarJson,'latitude':latitude,'longitude':longitude})
xhttp.send(msgJson);
The post request works absolutely fine with my express app code below.
var express = require('express');
// require our dependencies
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var app = express();
var port = process.env.PORT || 3100;
var corsOptions = {
credentials: false
};
// use body parser
app.use(bodyParser.urlencoded({extended: true, limit: 1024 * 1024 * 10000, parameterLimit: 1000000*1000}));
app.use(bodyParser.json({type: 'application/json', extended: false, limit: 1024 * 1024 * 10000, parameterLimit: 1000000*1000}));
// route our app
var router = require('./app/routes');
app.use('/', router);
var server
// start the server
server = app.listen(port, function() {
console.log('app started ' +port );
});
However I am struggling to replicate the post request above in post man for testing (purposes).
I believe that the following post request should do the trick but when my app recieves this post request the body of the request is always empty. Why? It seems that the body parser isnt doing it's job.
What I am doing wrong in my post request in postman, how can I replicate my javascript post request exactly?
You are doing two different types of request here. Your website code is sending a JSON string with the contents of the 'files' embedded into it:
let radFile = {"radfile":"long string"}
let solarJson = {"key1":"value1","key2":"value2"}
let latitude = 45
let longitude = 24
msgJson=JSON.stringify({'radFile':radFile,'speedSolar':solarJson,'latitude':latitude,'longitude':longitude})
gives you a body of
{'radFile': {"radfile": "long string"}, 'speedSolar': {"key1":"value1", "key2":"value2"}, 'latitude': 45, 'longitude': 24}
However, when you are using Postman as you are, you are submitting 2 different pieces, a file (or 2) and the form values - you can use the postman echo site to see what you are actually submitting, in case you have questions in the future:
If you really want to replicate your original version, you can do this - a raw body of type json, and fill in the details: