I have a node.js + Express application. It has a webhook that I have provided to a third party service. The service sends a POST request to my webhook with JSON body which looks something like this:
{"split_info" : "null", "customerName" : "Merchant Name",
"additionalCharges" : "null", "paymentMode":"CC",
"hash":"a31ff1b91fd9b8ae9c82f38b02348d21fsdfd86cc828ac9a0acf82050996372cc656de3db0fe3bf9af52b73a182a77787241f3e19ec893391607301b03e70db8",
"status" : "Release Payment", "paymentId" : "551731" ,
"productInfo":"productInfo", "customerEmail":"test#gmail.com",
"customerPhone":"9876543212", "merchantTransactionId":"jnn",
"amount":"100.0", "udf2":"null", "notificationId" :"4", "udf1":"null",
"udf5":"null", "udf4":"null", "udf3":"null","error_Message":"No
Error"}
I am using body-parser module to read POST data. However when I do req.body it gives [object Object], if I do JSON.stringify(req.body), it gives {} i.e. empty. If I try to access the keys in the response like req.body.paymentMode then it gives undefined.
Here is my router code for the webhook: mywebhook.js
var express = require('express');
var router = express.Router();
router.post('/success', function(req, res){
//this is where I need to strip the JSON request
//req.body or JSON.stringify(req.body) or anything that works
//if everything is okay then I send
res.sendStatus(200);
});
module.exports = router;
My app.js looks like this:
var express = require('express');
var exphbs = require('express-handlebars');
var router = express.Router();
var bodyParser = require('body-parser');
var mywebhook = require('./routes/mywebhook');
var app = express();
.
.
.
app.use(bodyParser.urlencoded({'extended':'true'})); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use('/callwebhook', mywebhook);
.
.
.
so on
Pretty sure I am missing something or doing something wrong, but I am not able to figure it out.
Thanks.
I finally found what was going on.
The way the body-parser works is that it will only try to parse a request in which they understand the Content-Type. This is mainly so you can stack them (app.use multiple parser types without conflict) and also because you typically don't want to parse a request that's going to fail (Content-Type: text/html is unlikely to ever get through a JSON.parse, for example).
I ended up getting sent */*; charset=UTF-8 which is not even a valid Content-Type header value period. The body-parser module refused to accept it, since that is gibberish. This module does allow you to setup a function that lets you put any custom logic you want to perform the filtering.
I had to put the body parser in my router code just for this webhook case.
var bodyParser = require('body-parser');
var customParser = bodyParser.json({type: function(req) {
return req.headers['content-type'] === '*/*; charset=UTF-8';
}});
router.post('/success', customParser, function(req, res){
console.log(JSON.stringify(req.body));
});
#svens thank you for your help.
Related
I try to use Postman for generating some post transaction of my web but when I check the post method of my code it print the empty {} and add the empty {} to my list. I try to use middleware but the problem is still occurring.
This is my code.
// my code at restaurant.js
const express = require("express");
const router = express.Router();
const restaurants = require("../data")
router.get("/",(req,res) =>{
res.json(restaurants);
}
)
router.get("/:id",(req,res) =>{
const restaurantid = Number.parseInt(req.params.id,10);
const restaurant = restaurants.find((restaurant) => restaurant.id === restaurantid);
res.json(restaurant);
})
router.post("/",(req,res)=>{
console.log(req.body);
new_restaurant = req.body;
restaurants.push(new_restaurant);
res.json(new_restaurant);
}
)
module.exports = router;
//my code at index.js
const express = require("express");
const app = express();
const router = express.Router();
const restaurantsRouter = require("./routes/restaurants.js");
// Middleware
app.use(express.json());
app.use(express.urlencoded({extended:false}));
// Routes
app.use("/apis/restaurants",restaurantsRouter);
app.get("/",(req,res)=>{
res.send("<h1>Hello Express</h1>");
});
app.listen(3000,()=> {
console.log("Listening to port 3000");
})
module.exports = router;
The general reasons for an empty req.body on an incoming POST request are as follows:
You are failing to send the body properly with whatever client is sending the request.
You are failing to set the right content-type with the request that matches the type of the body data you are sending. If you're sending JSON, then you will need to make sure the incoming request has the content-type application/json.
You don't have the right middleware installed or working properly that will match the incoming content-type, read the body from the incoming stream, parse it and put the parsed results in req.body.
The middleware for parsing that content-type is not registered before your route handler in Express.
Some other middleware is "eating" the body before your middleware so the body is empty when it gets to your JSON middleware.
So, you will need to go through your POST request and eliminate each of these possibilities until you find the problem.
This is my code:
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get('/',function(req,res){
res.sendfile("index.html");
});
app.post('/login',function(req,res){
console.log(req.body)
var user_name=req.body.user;
var password=req.body.password;
console.log("User name = "+user_name+", password is "+password);
res.end("yes");
});
app.listen(3000,function(){
console.log("Started on PORT 3000");
})
I set a console in post method function but it displayed:
{}
User name = undefined, password is undefined
I couldn't get any data from response. I had lookup doc but I couldn't find any error. I don't still understand. What mistake did i make?
You should send your data using Postman with the content-type:application/json in the header. This will ensure that the server receives the data in JSON format.
I know what happens!
If I want to send data in form-data, here has good solution helps me:
Result is undefined when I use form-data in Postman
If I use x-www-form-urlencoded to send data, it's actually valid!
I find when postman send json data without content-type:application/json in headers, it's definitely error. Now, I have added it. It can be valid.
Thanks, everyone!
I just installed the latest versions of modules. I can not get any GET or POST variables. What i do wrong?
NODE: v0.12.2
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
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))
});
app.listen(3000,function(){
console.log("Started on PORT 3000");
})
http://localhost:3000/?token=devvvvv GET returns:
you posted:
{}
Thanks for answers, but problem with POST does not solved...
POST token=as123ds on http://localhost:3000/ return empty array in req.body
How can i solve this?
You are submitting parameters via the query string and attempting to access them through the request body which in this case is empty.
The token parameter will be available in request.query like so:
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.query.token, null, 2))
});
If you only plan to submit parameters in the query string you should not need to mount the body-parser middleware at all.
You should be using the req.query:
req.query
An object containing a property for each query string parameter in the route. If there is no query string, it is the empty object, {}.
api link
You are parsing JSON from the request, so the POST from client must have 'Content-Type': 'application/json' in HTTP header. If not, you'll have empty request.body at server side.
bodyparser module requires the http request's "Content-type" property equal to "application/json". It won't work for other values.
You have to check the request content type in the client, this link may help
Node (Express) request body empty
This is because bodyParser parses application/json,
application/x-www-form-encoded and multipart/form-data, and it selects
which parser to use based on the Content-Type.
I am working on a simple texteditor that saves and loads text files through an Node/ExpressJS server. Loading is fine, but saving doesn't work yet due to me not being able to transmit the data to the server-app correctly.
I send the data via XMLHttpRequest to the server in a POST request, which works fine according to the network-profiler in dev-tools, the 'handler_save' function is called, but no parameters are received.
What am I doing wrong? (here is a snippet of the server code, altered for demonstration:)
express = require('express')();
function init_save_load(){
var bodyParser = require('body-parser');
express.use(bodyParser.urlencoded({ extended: true }));
express.use('/save', handler_save );
express.use('/load', handler_load );
}
...
function handler_save(req, res){
console.log(req.body); // "{name:post.txt,data:testing}"
}
make sure you are parsing the request body so it can work
var bodyParser = require('body-parser');
app.use(bodyParser());
bodyParser is a part of "Connect", a set of middlewares for node.js. Here's the real docs and source from Connect: http://www.senchalabs.org/connect/bodyParser.html
finally console log the req.body and see what is in there
console.log(req.body)
Not only do you need to use a body parsing middleware as Abdul mentioned, but your request needs to have the correct Content-Type. Currently you are sending Content-Type: text/plain, but it should be Content-Type: application/x-www-form-urlencoded for simple forms or Content-Type: multipart/form-data for forms containing files.
There are similar SO questions, but I could not find a precise answer to this issue.
I need to push back some text from the client side to the server side from time to time. The user side does not expect an answer from the server side. I though I would use POST as following:
var request = new XMLHttpRequest();
request.open('POST', MY_URL, true);
request.setRequestHeader('Content-Type', 'text/html;charset=utf-8');
request.send(myMsg);
From Chrome, I can see that the header and payload are correct. The status is 200 OK.
On the server side, I try to retrieve the body content as following:
function myFunction(req, res) {
console.log("Reached myFunction, reqBody is: '" + req.body + "'");
res.end();
}
But I get:
Reached myFunction, reqBody is: 'undefined'
What am I doing wrong? Should I use 'application/json; charset=utf-8' with a JSON instead?
Update
I have been doing some more research and the req object on the server side does not have a body property. However, the headers is fine.
I initiate my application with the following:
var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
...
self.app = express();
...
self.app.use(bodyParser());
self.app.use(cookieParser());
Any ideas?
When using the body-parser middleware, it's important that the content type matches. In this case, you've specified text/html, so you should use the bodyParser.text() middleware. In addition, you need to specify text/html as the type. So a full example would look like:
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.text({
type: "text/html"
}));
app.post("/test", function(req, res) {
console.log(req.body);
res.end();
});
app.listen(3000);
You could also use a wildcard, such as type: "text/*" for the options to bodyParser.text().
When I ran this using your example, I see "hi" output to the console when I hit /test.
try :
request.setRequestHeader('Content-Type', "application/x-www-form-urlencoded");
this might help.