I need to process a HTTP push request using Node.js express.
The request is sending the body in XML format, that's why I chose the body-parser-xml package for parsing.
My problem is, that the body isn't properly parsed – I guess because the package doesn't recognize the mime type of the transferred body.
The endpoint:
const express = require('express');
const bodyParser = require('body-parser');
require('body-parser-xml')(bodyParser);
const app = express();
const PORT = 8085;
app.use(express.urlencoded({ extended: true }));
app.use(bodyParser.xml({
limit:'25MB'
}));
app.post('/feed', function (req, res, body) {
console.log(req.headers);
console.log(req.body);
res.status(200).end();
});
The output:
{
host: 'localhost:8085',
accept: '*/*',
'x-meta-feed-type': '1',
'x-meta-feed-parameters': 'feed params',
'x-meta-default-filename': 'filename.xml',
'x-meta-mime-type': 'text/xml',
'content-length': '63'
encoding: 'UTF-8',
connection: 'Keep-Alive'
}
{
'<data id': '"1234"><name>Test</name><title>Test1234</title></data>'
}
I'm not able to change the request itself (it's external), only the Node.js endpoint.
Any idea how to process the content properly?
Thanks for your help!
The request has apparently been parsed by the
app.use(express.urlencoded({ extended: true }));
middleware, which means that it must have had Content-Type: application/x-www-form-urlencoded. Remove the two app.use lines, because they make "global" body-parsing decisions (for every request), whereas you need a special treatment only for one type of request.
If you instantiate the XML body parser with the "non-standard" (that is, wrong) type, it will parse the content as XML:
app.post('/feed',
bodyParser.xml({type: "application/x-www-form-urlencoded"}),
function (req, res) {
console.log(req.headers);
console.log(req.body);
res.status(200).end();
});
this is my index.js code and it returns an empty object even though data is passed on from the front-end
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
app.use(express.json());
app.post("/api/register", (req, res) => {
console.log(req.body);
res.json({ status: "ok" });
});
app.listen(8000, () => {
console.log("listening on port 8000 . . . ");
});
For the specific case you're talking about, you usually need oa body parser to be able to access the form input fields. The minimum example that I advice you to build above it is the following:
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
Some other hints
Make sure that the request is being submitted with the header Content-Type: application/x-www-form-urlencoded or Content-Type: application/json
Check if there any CORS problems
Here's More reference for you
The main reason this does not work is
some how the data passed in body is in text format while req.body is
expecting json data
make sure to double chek the 'Content-Type':'application/json' is set on the request headers
if you are using multipart/form-data or require a file upload from frontend you will need a multer as middleware for your post/patch requests, otherwise you can set your frontend to send application/json
[edit]
this line looks missing from your index.js
app.use(express.urlencoded({extended: true}))
I'm trying to do a POST request using raw json.
In the Body tab I have "raw" selected with this body:
{
"name": "book"
}
On the Node js side I'm doing res.send(JSON.stringify(req.body))
router.post('/', (req, res, next) => {
res.send(JSON.stringify(req.body));
}
And in POSTMAN response I receive:
{"{\n\"name\": \"book\"\n}":""}
When expected something like
{"name":"book"}
Have no idea - where could be a reason for it?
You'll need to use the Express JSON body parser, install using
npm install body-parser;
Then:
const bodyParser = require('body-parser');
app.use(bodyParser.json());
Once you do this, the JSON data will be parsed correctly and when you send it back it will render correctly.
Also make sure you have your Content-Type header set to "application/json" in your Postman request (go to "Headers" and add a new "Content-Type" header with value "application/json")
Here's a simple express app that will echo any JSON POST:
const express = require("express");
const port = 3000;
const app = express();
const bodyParser = require('body-parser')
app.use(bodyParser.json());
app.post('/', (req, res, next) => {
console.log("Body: ", req.body);
res.send(JSON.stringify(req.body));
})
app.listen(port);
console.log(`Serving at http://localhost:${port}`);
If you're on Express v4.16.0 onwards, try to add this line before app.listen():
app.use(express.json());
This is a built-in middleware function in Express. It parses incoming requests with JSON payloads and is based on body-parser.
Looks to me like its not a fault of Postman, but your NodeJS service is applying JSON.stringify twice?
Can you log the response type from the server to console to check whether its already json content or not?
try with hard coded json response and then with dynamic variable
res.json({"name":"book"});
I'm receiving data on a webhook URL as a POST request. Note that the content type of this request is application/x-www-form-urlencoded.
It's a server-to-server request. And On my Node server, I simply tried to read the received data by using req.body.parameters but resulting values are "undefined"?
So how can I read the data request data? Do I need to parse the data? Do I need to install any npm module? Can you write a code snippet explaining the case?
If you are using Express.js as Node.js web application framework, then use ExpressJS body-parser.
The sample code will be like this.
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
// With body-parser configured, now create our route. We can grab POST
// parameters using req.body.variable_name
// POST http://localhost:8080/api/books
// parameters sent with
app.post('/api/books', function(req, res) {
var book_id = req.body.id;
var bookName = req.body.token;
//Send the response back
res.send(book_id + ' ' + bookName);
});
You must tell express to handle urlencoded data, using an specific middleware.
const express = require('express');
const app = express();
app.use(express.urlencoded({
extended: true
}))
And on your route, you can get the params from the request body:
const myFunc = (req,res) => {
res.json(req.body);
}
The accepted answer uses express and the body-parser middleware for express. But if you just want to parse the payload of an application/x-www-form-urlencoded ContentType sent to your Node http server, then you could accomplish this without the extra bloat of Express.
The key thing you mentioned is the http method is POST. Consequently, with application/x-www-form-urlencoded, the params will not be encoded in the query string. Rather, the payload will be sent in the request body, using the same format as the query string:
param=value¶m2=value2
In order to get the payload in the request body, we can use StringDecoder, which decodes buffer objects into strings in a manner that preserves the encoded multi-byte UTF8 characters. So we can use the on method to bind the 'data' and 'end' event to the request object, adding the characters in our buffer:
const StringDecoder = require('string_decoder').StringDecoder;
const http = require('http');
const httpServer = http.createServer((req, res) => {
const decoder = new StringDecoder('utf-8');
let buffer = '';
req.on('data', (chunk) => {
buffer += decoder.write(chunk);
});
req.on('end', () => {
buffer += decoder.end();
res.writeHead(200, 'OK', { 'Content-Type': 'text/plain'});
res.write('the response:\n\n');
res.write(buffer + '\n\n');
res.end('End of message to browser');
});
};
httpServer.listen(3000, () => console.log('Listening on port 3000') );
Express 4.16+ has implemented their own version of body-parser so you do not need to add the dependency to your project.
app.use(express.urlencoded()); //Parse URL-encoded bodies
Non-deprecated alternative to body-parser in Express.js
If you are creating a NodeJS server without a framework like Express or Restify, then you can use the NodeJS native querystring parser. The content type application/www-form-urlencoded format is the same as the querystring format, so we can reuse that built-in functionality.
Also, if you're not using a framework then you'll need to actually remember to read your body. The request will have the method, URL, and headers but not the body until you tell it to read that data. You can read up about that here: https://nodejs.org/dist/latest/docs/api/http.html
If you are using restify, it would be similar:
var server = restify.createServer()
server.listen(port, () => console.log(`${server.name} listening ${server.url}`))
server.use(restify.plugins.bodyParser()) // can parse Content-type: 'application/x-www-form-urlencoded'
server.post('/your_url', your_handler_func)
I have this as configuration of my Express server
app.use(app.router);
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));
app.set('view engine', 'ejs');
app.set("view options", { layout: true });
//Handles post requests
app.use(express.bodyParser());
//Handles put requests
app.use(express.methodOverride());
But still when I ask for req.body.something in my routes I get some error pointing out that body is undefined. Here is an example of a route that uses req.body :
app.post('/admin', function(req, res){
console.log(req.body.name);
});
I read that this problem is caused by the lack of app.use(express.bodyParser()); but as you can see I call it before the routes.
Any clue?
UPDATE July 2020
express.bodyParser() is no longer bundled as part of express. You need to install it separately before loading:
npm i body-parser
// then in your app
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// create application/json parser
var jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
res.send('welcome, ' + req.body.username)
})
// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
// create user in req.body
})
See here for further info
original follows
You must make sure that you define all configurations BEFORE defining routes. If you do so, you can continue to use express.bodyParser().
An example is as follows:
var express = require('express'),
app = express(),
port = parseInt(process.env.PORT, 10) || 8080;
app.configure(function(){
app.use(express.bodyParser());
});
app.listen(port);
app.post("/someRoute", function(req, res) {
console.log(req.body);
res.send({ status: 'SUCCESS' });
});
Latest versions of Express (4.x) has unbundled the middleware from the core framework. If you need body parser, you need to install it separately
npm install body-parser --save
and then do this in your code
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
Express 4, has built-in body parser. No need to install separate body-parser. So below will work:
export const app = express();
app.use(express.json());
No. You need to use app.use(express.bodyParser()) before app.use(app.router). In fact, app.use(app.router) should be the last thing you call.
The Content-Type in request header is really important, especially when you post the data from curl or any other tools.
Make sure you're using some thing like application/x-www-form-urlencoded, application/json or others, it depends on your post data. Leave this field empty will confuse Express.
First make sure , you have installed npm module named 'body-parser' by calling :
npm install body-parser --save
Then make sure you have included following lines before calling routes
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
As already posted under one comment, I solved it using
app.use(require('connect').bodyParser());
instead of
app.use(express.bodyParser());
I still don't know why the simple express.bodyParser() is not working...
Add in your app.js
before the call of the Router
const app = express();
app.use(express.json());
The question is answered. But since it is quite generic and req.body undefined is a frequent error, especially for beginners, I find this is the best place to resume all that I know about the problem.
This error can be caused by the following reasons:
1. [SERVER side] [Quite often] Forget or misused parser middleware
You need to use appropriate middleware to parse the incoming requests. For example, express.json() parses request in JSON format, and express.urlencoded() parses request in urlencoded format.
const app = express();
app.use(express.urlencoded())
app.use(express.json())
You can see the full list in the express documentation page
If you can't find the right parser for your request in Express (XML, form-data...), you need to find another library for that. For example, to parse XML data, you can use this library
You should use the parser middleware before the route declaration part (I did a test to confirm this!). The middleware can be configured right after the initialization express app.
Like other answers pointed out, bodyParser is deprecated since express 4.16.0, you should use built-in middlewares like above.
2. [CLIENT side] [Rarely] Forget to send the data along with the request
Well, you need to send the data...
To verify whether the data has been sent with the request or not, open the Network tabs in the browser's devtools and search for your request.
It's rare but I saw some people trying to send data in the GET request, for GET request req.body is undefined.
3. [SERVER & CLIENT] [Quite often] Using different Content-Type
Server and client need to use the same Content-Type to understand each other. If you send requests using json format, you need to use json() middleware. If you send a request using urlencoded format, you need to use urlencoded()...
There is 1 tricky case when you try to upload a file using the form-data format. For that, you can use multer, a middleware for handling multipart/form-data.
What if you don't control the client part? I had a problem when coding the API for Instant payment notification (IPN). The general rule is to try to get information on the client part: communicate with the frontend team, go to the payment documentation page... You might need to add appropriate middleware based on the Content-Type decided by the client part.
Finally, a piece of advice for full-stack developers :)
When having a problem like this, try to use some API test software like Postman. The object is to eliminate all the noise in the client part, this will help you correctly identify the problem.
In Postman, once you have a correct result, you can use the code generation tool in the software to have corresponded code. The button </> is on the right bar. You have a lot of options in popular languages/libraries...
app.use(express.json());
It will help to solve the issue of req.body undefined
// Require body-parser (to receive post data from clients)
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
Looks like the body-parser is no longer shipped with express. We may have to install it separately.
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
// parse application/vnd.api+json as json
app.use(bodyParser.json({ type: 'application/vnd.api+json' }))
app.use(function (req, res, next) {
console.log(req.body) // populated!
Refer to the git page https://github.com/expressjs/body-parser for more info and examples.
In case anyone runs into the same issue I was having; I am using a url prefix like
http://example.com/api/
which was setup with router
app.use('/api', router);
and then I had the following
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
What fixed my issue was placing the bodyparser configuration above app.use('/api', router);
Final
// setup bodyparser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//this is a fix for the prefix of example.com/api/ so we dont need to code the prefix in every route
app.use('/api', router);
Most of the time req.body is undefined due to missing JSON parser
const express = require('express');
app.use(express.json());
could be missing for the body-parser
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));
and sometimes it's undefined due to cros origin so add them
const cors = require('cors');
app.use(cors())
The middleware is always used as first.
//MIDDLEWARE
app.use(bodyParser.json());
app.use(cors());
app.use(cookieParser());
before the routes.
//MY ROUTES
app.use("/api", authRoutes);
express.bodyParser() needs to be told what type of content it is that it's parsing. Therefore, you need to make sure that when you're executing a POST request, that you're including the "Content-Type" header. Otherwise, bodyParser may not know what to do with the body of your POST request.
If you're using curl to execute a POST request containing some JSON object in the body, it would look something like this:
curl -X POST -H "Content-Type: application/json" -d #your_json_file http://localhost:xxxx/someRoute
If using another method, just be sure to set that header field using whatever convention is appropriate.
Use app.use(bodyparser.json()); before routing. // .
app.use("/api", routes);
History:
Earlier versions of Express used to have a lot of middleware bundled with it. bodyParser was one of the middleware that came with it. When Express 4.0 was released they decided to remove the bundled middleware from Express and make them separate packages instead. The syntax then changed from app.use(express.json()) to app.use(bodyParser.json()) after installing the bodyParser module.
bodyParser was added back to Express in release 4.16.0, because people wanted it bundled with Express like before. That means you don't have to use bodyParser.json() anymore if you are on the latest release. You can use express.json() instead.
The release history for 4.16.0 is here for those who are interested, and the pull request is here.
Okay, back to the point,
Implementation:
All you need to add is just add,
app.use(express.json());
app.use(express.urlencoded({ extended: true}));
app.use(app.router); // Route will be at the end of parser
And remove bodyParser (in newer version of express it is not needed)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
And Express will take care of your request. :)
Full example will looks like,
const express = require('express')
const app = express()
app.use(express.json())
app.use(express.urlencoded({ extended: true}));
app.post('/test-url', (req, res) => {
console.log(req.body)
return res.send("went well")
})
app.listen(3000, () => {
console.log("running on port 3000")
})
You can try adding this line of code at the top, (after your require statements):
app.use(bodyParser.urlencoded({extended: true}));
As for the reasons as to why it works, check out the docs: https://www.npmjs.com/package/body-parser#bodyparserurlencodedoptions
Firsl of all, ensure you are applying this middleware (express.urlencoded) before routes.
let app = express();
//response as Json
app.use(express.json());
//Parse x-www-form-urlencoded request into req.body
app.use(express.urlencoded({ extended: true }));
app.post('/test',(req,res)=>{
res.json(req.body);
});
The code express.urlencoded({extended:true}) only responds to x-www-form-urlencoded posts requests, so in your ajax/XMLHttpRequest/fetch, make sure you are sending the request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); header.
Thats it !
in Express 4, it's really simple
const app = express()
const p = process.env.PORT || 8082
app.use(express.json())
This occured to me today. None of above solutions work for me. But a little googling helped me to solve this issue. I'm coding for wechat 3rd party server.
Things get slightly more complicated when your node.js application requires reading streaming POST data, such as a request from a REST client. In this case, the request's property "readable" will be set to true and the POST data must be read in chunks in order to collect all content.
http://www.primaryobjects.com/CMS/Article144
Wasted a lot of time:
Depending on Content-Type in your client request
the server should have different, one of the below app.use():
app.use(bodyParser.text({ type: 'text/html' }))
app.use(bodyParser.text({ type: 'text/xml' }))
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }))
app.use(bodyParser.json({ type: 'application/*+json' }))
Source: https://www.npmjs.com/package/body-parser#bodyparsertextoptions
Example:
For me,
On Client side, I had below header:
Content-Type: "text/xml"
So, on the server side, I used:
app.use(bodyParser.text({type: 'text/xml'}));
Then, req.body worked fine.
To work, you need to app.use(app.router) after app.use(express.bodyParser()), like that:
app.use(express.bodyParser())
.use(express.methodOverride())
.use(app.router);
var bodyParser = require('body-parser');
app.use(bodyParser.json());
This saved my day.
I solved it with:
app.post('/', bodyParser.json(), (req, res) => {//we have req.body JSON
});
In my case, it was because of using body-parser after including the routes.
The correct code should be
app.use(bodyParser.urlencoded({extended:true}));
app.use(methodOverride("_method"));
app.use(indexRoutes);
app.use(userRoutes);
app.use(adminRoutes);
As I get the same problem, although I know BodyParser is no longer used
and I already used the app.use(express.json())
the problem was {FOR ME}:
I was placing
app.use(express.json())
after
app.use('api/v1/example', example) => { concerns the route }
once I reorder those two lines;
1 - app.use(express.json())
2 - app.use('api/v1/example', example)
It worked perfectly
If you are using some external tool to make the request, make sure to add the header:
Content-Type: application/json
This is also one possibility: Make Sure that you should write this code before the route in your app.js(or index.js) file.
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());