I have the following setup in my app.js:
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
var router = express.Router();
require('./routes/index')(router);
app.use(router);
In my routes/index.js I have all the routes defined:
module.exports = function (router) {
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Home' });
});
router.post('/', function(req, res, next) {
console.log(req.body);
});
}
Then in my app entry point bin/server.js:
var app = require('../app');
var debug = require('debug')('NodeJSDemo:server');
var http = require('http');
var port = 3000;
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
When I make a POST call on http://localhost:3000/ with a request body, in the console log console log request body is undefined.
Is there anything wrong with my setup? From this post Express.js req.body undefined it seems as long as I call
app.use(bodyParser.json())
before loading routes, it should be fine but seems like it does not.
The problem arises from what type of resource you are sending on your POST request.
Your bodyParser.json() is ONLY parsing json format. Or in other words if you simply POST a simple form that in most cases defaults to application/x-www-form-urlencoded you will not get the body object.
As it is stated in the documentation:
Returns middleware that only parses json and only looks at requests
where the Content-Type header matches the type option.
and
type - The type option is used to determine what media type the middleware
will parse.
Defaults to application/json.
The solution would be to implement and cather from other scenarios so:
application/x-www-form-urlencoded
app.use(bodyParser.urlencoded())
multipart/form-data
Express does not parse multipart bodies as stated in the documentation:
This does not handle multipart bodies, due to their complex and
typically large nature. For multipart bodies, you may be interested in
the following modules:
busboy and connect-busboy
multiparty and connect-multiparty
formidable
multer
For Express versions: +4.17.0
You could not include the bodyParser dependency. And use the express built-in methods as:
express.json()
express.text()
express.urlencoded()
They are built based on the bodyParser module so instead calling bodyParser.json(). You would do express.json() and achieve the same results.
Source:
https://expressjs.com/en/resources/middleware/body-parser.html#bodyparserurlencodedoptions
Related
Here's my app.js file.
var express = require('express'),
bodyParser = require('body-parser'),
oauthServer = require('oauth2-server'),
oauth_model = require('./app_modules/oauth_model')
const app = express()
app.use(bodyParser.urlencoded({ extended: true }));
var jsonParser = bodyParser.json();
app.oauth = oauthServer({
model: oauth_model, // See below for specification
grants: ['password', 'refresh_token'],
debug: process.env.OAUTH_DEBUG,
accessTokenLifetime: 172800,
refreshTokenLifetime: 172800,
authCodeLifetime: 120,
});
// Oauth endpoint.
app.all('/oauth/token', app.oauth.grant());
// User registration endpoint.
app.post('/users', jsonParser, require('./routes/register.js'));
// Get user details.
app.get('/users', app.oauth.authorise(), require('./routes/users.js'));
app.post('/', app.oauth.authorise(), require('./routes/test.js'));
app.use(app.oauth.errorHandler());
app.listen(3000, function () {
console.log('Mixtra app listening on port 3000!')
})
When I send an invalid json body with POST request to localhost:3000/users the request goes to register.js and the validation code works there.
but strangely when I send valid JSON body, it says "Cannot POST /users" with a 404 Not Found HTTP status code and nothing in terminal log.
Note: I'm using postman to send the api requests.
It would be really great if someone could help me with this.
Thanks,
Joy
I don't see you using the jsonParser
You should use it before sending any json to it
app.use(jsonParser);
This question is very similar to How to disable Express BodyParser for file uploads (Node.js). The answer they have provided is for Express3 and I have tried the solution with the updated Express 4 and it does not seem to work.
I'm using Node.js + Express to build a web application. I am using another library,BodyParser,to parse post parameters. However, I would like to have more granular access to multipart form-data POSTS as they come - I need to pipe the input stream to another server, and want to avoid downloading the whole file first.
All file uploads are parsed automatically and uploaded and available using "request.files" before they ever get to any of my functions.
Is there a way for me to disable the BodyParser for multipart formdata posts without disabling it for everything else?
This is my app.js file. In here I am defining an authentication route which shouldn't except any files just a token (POST parameter). I am also defining another route called upload. This route accepts a file and also POST parametes (form-data). This route only gets called if the authentication route allows it. So in the authetnication route I don't want form-data to be allowed, but in the upload route I do. So when I get a request to uplaod something it will go through the auth route and then the upload route. Due to this I need to allow the auth route to allow files (form-data) which I do not want. So I want bodyparser to work in the auth route while I use mutler (another library) in my upload path to parse my upload files. In my real application though of course I have many more routes and would like to code it as cleanly as I can with the least amount of redundancy.
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended: true
}));
var route_auth = require('./routes/auth');
app.use('/api/post/*', route_auth);
var route_upload = require('./routes/post/upload');
app.use('/api/post/upload', route_upload );
app.listen(3000, function() {
console.log('Server listening on port 3000!')
});
My auth route looks something like this:
router.post("/", function(req, res, next) {
if(everythingiscool){
return next()
}
next(err);
});
My upload route looks like this:
var express = require('express');
var router = express.Router();
var multer = require('multer')
var upload = multer({ dest: 'uploads/' });
router.post("/", upload.single('avatar'), function(req, res, next) {
//work with req.file
});
Wrap the bodyParse middleware in a function that checks if the request body's Content-Type is multipart or not:
var isMultipart = /^multipart\//i;
var bodyParser = require('body-parser');
var urlencodedMiddleware = bodyParser.urlencoded({ extended: true });
app.use(function (req, res, next) {
var type = req.get('Content-Type');
if (isMultipart.test(type)) return next();
return urlencodedMiddleware(req, res, next);
});
Instead of disabling, why not enable the middleware on the routes/routers where you need it?
For individual routes, you can just add it as another argument before your actual route handler, for example:
app.post('/upload', bodyParser, (req, res) => {
// route logic here
});
When using the following:
var app = require('express')();
var bodyParser = require('body-parser');
app.post('/test', bodyParser.json(), function(req, res) {
res.json(req.body);
});
var port = 4040;
app.listen(port, function() {
console.log('server up and running at port: %s', port);
});
and the following post from Postman:
I get an empty response. I've followed a lot of threads on using bodyParser.json() and for some reason I'm still receiving an empty object in response. What am I missing?
To make bodyParser.json works you should provide Content-Type header with value application/json in your requests.
A safer way to use body-parser would be to apply it as middleware for the entire app. The code will have to be refactored in this manner:
// Permit the app to parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// Use body-parser as middleware for the app.
app.use(bodyParser.json());
app.post('/test', function(req, res) {
res.json(req.body);
});
When you make a request on Postman, make sure to select the x-www-form-urlencoded tab as opposed to the raw tab.
Being a newbie in Nodejs, I jumped right into writing a simple app without really reading up on good security practices. I just found out that using bodyParser() for all routes is actually a bad thing because it allows for DOS attack using multipart files.
A recommended fix is to only load specific modules depending on the route. ie, for multipart fileupload, use multipart. For regular POST without file uploads (ie, text form submission), use express.json(), express.urlencoded().
Or another option is to use busboy with connect-busboy. But the thing I'm confused on is how I can specify which route should handle multipart data and which should not? Otherwise, wouldn't I have the same problem as with bodyParser?
Furthermore, busboy docs says it does not handle GET:
If you find that req.busboy is not defined in your code when you expect it to be, check that the following conditions are met. If they are not, req.busboy won't be defined:
1. The request method is not GET or HEAD
So, I'm even more confused how I would parse params in a GET. I think bodyParser does this for me so I could access data with req.params.
For example, how would I migrate away from bodyParser() to busboy/connect-busboy with this simple app:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var bodyParser = require('body-parser');
app.use(bodyParser.json());
var busboy = require('connect-busboy');
app.use(busboy());
// How to use busboy to prevent multipart files here?
app.post("/form_data_no_fileupload", function(req, res) {
var somedata = req.body.somedata;
});
// Use busboy to handle both regular form data + fileuploads
app.post("/form_data_AND_fileupload", function(req, res) {
});
// What would handle GET without bodyparser?
app.get("/get_something", function(req, res) {
var params = req.params;
});
http.listen(3000, function() {});
[How] I can specify which route should handle multipart data and which should not?
All of Express' routing methods allow for providing middleware specific to the route. This includes Router methods.
app.METHOD(path, callback [, callback ...])
Depending on the body expected for an individual route, you can use different modules to handle each of them (rather than applying them to the entire application with app.use()).
var express = require('express');
var app = express();
var http = require('http').Server(app);
var bodyParser = require('body-parser');
var busboy = require('connect-busboy');
app.post("/form_data_no_fileupload",
bodyParser.urlencoded(),
function(req, res, next) {
// check that the request's body was as expected
if (!req.body) return next('route'); // or next(new Error('...'));
// ...
});
app.post("/form_data_AND_fileupload",
busboy({
limits: {
fileSize: 10 * 1024 * 1024
}
}),
function(req, res, next) {
// check that the request's body was as expected
if (!req.busboy) return next('route'); // or next(new Error('...'));
// ...
});
// ...
Furthermore, busboy docs says it does not handle GET.
So, I'm even more confused how I would parse params in a GET.
Busboy and BodyParser are designed for reading in and parsing the request's body, which GET and HEAD requests aren't expected to have.
For such requests, parameters can only be passed within the query-string within the URL, which Express parses itself. They're available via req.query.
app.get('/get_something', function () {
console.log(req.originalUrl);
// "/get_something?id=1
console.log(req.query);
// { id: "1" }
});
req.params represents any placeholders matched in the path by the route. These are available for any route, regardless of the method.
app.get('/thing/:id', function (req, res) {
console.log(req.originalUrl);
// "/thing/2"
console.log(req.params);
// { id: "2" }
});
I have the following Node.js code:
var express = require('express');
var app = express.createServer(express.logger());
app.use(express.bodyParser());
app.post('/', function(request, response) {
response.write(request.body.user);
response.end();
});
Now if I POST something like:
curl -d user=Someone -H Accept:application/json --url http://localhost:5000
I get Someone as expected. Now, what if I want to get the full request body? I tried doing response.write(request.body) but Node.js throws an exception saying "first argument must be a string or Buffer" then goes to an "infinite loop" with an exception that says "Can't set headers after they are sent."; this also true even if I did var reqBody = request.body; and then writing response.write(reqBody).
What's the issue here?
Also, can I just get the raw request without using express.bodyParser()?
Starting from express v4.16 there is no need to require any additional modules, just use the built-in JSON middleware:
app.use(express.json())
Like this:
const express = require('express')
app.use(express.json()) // <==== parse request body as JSON
app.listen(8080)
app.post('/test', (req, res) => {
res.json({requestBody: req.body}) // <==== req.body will be a parsed JSON object
})
Note - body-parser, on which this depends, is already included with express.
Also don't forget to send the header Content-Type: application/json
Express 4.0 and above:
$ npm install --save body-parser
And then in your node app:
const bodyParser = require('body-parser');
app.use(bodyParser);
Express 3.0 and below:
Try passing this in your cURL call:
--header "Content-Type: application/json"
and making sure your data is in JSON format:
{"user":"someone"}
Also, you can use console.dir in your node.js code to see the data inside the object as in the following example:
var express = require('express');
var app = express.createServer();
app.use(express.bodyParser());
app.post('/', function(req, res){
console.dir(req.body);
res.send("test");
});
app.listen(3000);
This other question might also help: How to receive JSON in express node.js POST request?
If you don't want to use the bodyParser check out this other question: https://stackoverflow.com/a/9920700/446681
As of Express 4, the following code appears to do the trick.
Note that you'll need to install body-parser using npm.
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.listen(8888);
app.post('/update', function(req, res) {
console.log(req.body); // the posted data
});
For 2019, you don't need to install body-parser.
You can use:
var express = require('express');
var app = express();
app.use(express.json())
app.use(express.urlencoded({extended: true}))
app.listen(8888);
app.post('/update', function(req, res) {
console.log(req.body); // the posted data
});
You should not use body-parser it is deprecated. Try this instead
const express = require('express')
const app = express()
app.use(express.json()) //Notice express.json middleware
The app.use() function is used to mount the specified middleware function(s) at the path which is being specified. It is mostly used to set up middleware for your application.
Now to access the body just do the following
app.post('/', (req, res) => {
console.log(req.body)
})
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json())
var port = 9000;
app.post('/post/data', function(req, res) {
console.log('receiving data...');
console.log('body is ',req.body);
res.send(req.body);
});
// start the server
app.listen(port);
console.log('Server started! At http://localhost:' + port);
This will help you. I assume you are sending body in json.
This can be achieved without body-parser dependency as well, listen to request:data and request:end and return the response on end of request, refer below code sample. ref:https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/#request-body
var express = require('express');
var app = express.createServer(express.logger());
app.post('/', function(request, response) {
// push the data to body
var body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
// on end of data, perform necessary action
body = Buffer.concat(body).toString();
response.write(request.body.user);
response.end();
});
});
In my case, I was missing to set the header:
"Content-Type: application/json"
Try this:
response.write(JSON.stringify(request.body));
That will take the object which bodyParser has created for you and turn it back into a string and write it to the response. If you want the exact request body (with the same whitespace, etc), you will need data and end listeners attached to the request before and build up the string chunk by chunk as you can see in the json parsing source code from connect.
The accepted answer only works for a body that is compatible with the JSON format. In general, the body can be accessed using
app.use(
Express.raw({
inflate: true,
limit: '50mb',
type: () => true, // this matches all content types
})
);
like posted here. The req.body has a Buffer type and can be converted into the desired format.
For example into a string via:
let body = req.body.toString()
Or into JSON via:
let body = req.body.toJSON();
If you're lazy enough to read chunks of post data.
you could simply paste below lines
to read json.
Below is for TypeScript similar can be done for JS as well.
app.ts
import bodyParser from "body-parser";
// support application/json type post data
this.app.use(bodyParser.json());
// support application/x-www-form-urlencoded post data
this.app.use(bodyParser.urlencoded({ extended: false }));
In one of your any controller which receives POST call use as shown below
userController.ts
public async POSTUser(_req: Request, _res: Response) {
try {
const onRecord = <UserModel>_req.body;
/* Your business logic */
_res.status(201).send("User Created");
}
else{
_res.status(500).send("Server error");
}
};
_req.body should be parsing you json data into your TS Model.
I'm absolutely new to JS and ES, but what seems to work for me is just this:
JSON.stringify(req.body)
Let me know if there's anything wrong with it!
Install Body Parser by below command
$ npm install --save body-parser
Configure Body Parser
const bodyParser = require('body-parser');
app.use(bodyParser);
app.use(bodyParser.json()); //Make sure u have added this line
app.use(bodyParser.urlencoded({ extended: false }));
What you claim to have "tried doing" is exactly what you wrote in the code that works "as expected" when you invoke it with curl.
The error you're getting doesn't appear to be related to any of the code you've shown us.
If you want to get the raw request, set handlers on request for the data and end events (and, of course, remove any invocations of express.bodyParser()). Note that the data events will occur in chunks, and that unless you set an encoding for the data event those chunks will be buffers, not strings.
You use the following code to log post data:
router.post("/users",function(req,res){
res.send(JSON.stringify(req.body, null, 4));
});