Body-parser fails to/do not parse urlencoded parameters from GET request - node.js

I'm creating a web platform with a Nodejs server. I'm trying to retrieve urlencoded data sent from my front but can't manage to.
How I send the GET request :
xhr.open("GET", address + "?limit=1&offset=1",true);
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(null);
xhr.addEventListener("readystatechange", processRequest, false);
On the server side :
const bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: true });
app.get('/guid_list', urlencodedParser, function (req, res) {
console.log(req.body.limit);
console.log(req.body.offset);
var headerjwt = HeaderGetJWT(req);
...
}
I have no problem retrieving the jwt token I'm sending, but always get undefined for urlencoded parameters.
I was wondering if I should use multipart content type instead, since I'm sending both a token and urlencoded data ? And maybe "multer" module in that case, since body-Parser does not support that content type.

I would suggest accessing your parameters in Node.js as follows (since they are being passed as query parameters):
app.get('/guid_list', parser, function (req, res) {
console.log("req.query.limit:", req.query.limit);
console.log("req.query.offset:", req.query.offset);
});
or just log all parameters:
app.get('/guid_list', parser, function (req, res) {
console.log("req.query:", req.query);
});

Related

Parse XML body from HTTP Push request with Express & Node.js, using body-parser-xml

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();
});

xxx-form-encoded to application/json

My login functionalities in the backend accepts the parameters in xxx-form-encoded format from POSTMAN .. I am getting error when I change the format to application/json . Any thoughts on how to receive the request.body ?
authenticate: function(req, res, next) {
userModel.findOne({email:req.body.email}, function(err, userInfo){
if (err) {
next(err);
} else {
console.log(`The bcrypt value: ${bcrypt.compareSync(req.body.password, userInfo.password)}`)
if(userInfo != null && bcrypt.compareSync(req.body.password, userInfo.password)) {
const token = jwt.sign({id: userInfo._id}, req.app.get('secret'), { expiresIn: '1h' });
res.json({status:"success", message: "user found!!!", data:{user: userInfo, token:token}});
}else{
res.json({status:"error", message: "Invalid email/password!!!", data:null});
}
}
});
}
I think you need to add a middleware which parses your request body to json.
You can use body-parser to acheive it.
if you are using express you can do this to acheive it:
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.json({}));//this line is required to tell your app to parse the body as json
app.use(bodyParser.urlencoded({ extended: false }));
From body-parser docs :
bodyParser.urlencoded([options])
Returns middleware that only parses urlencoded bodies and only looks
at requests where the Content-Type header matches the type option.
This parser accepts only UTF-8 encoding of the body and supports
automatic inflation of gzip and deflate encodings.
A new body object containing the parsed data is populated on the
request object after the middleware (i.e. req.body). This object will
contain key-value pairs, where the value can be a string or array
(when extended is false), or any type (when extended is true).
Read body-parser documentation for details.

How can I read the data received in application/x-www-form-urlencoded format on Node server?

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&param2=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)

Using multiple parameters in URL, params between static url are not available

I am using express.js (v 4.13.4), node.js (v 0.12.5) and body-parser (v 1.13.2) to create a simple chat RESTful API.
I have this url path which must be called by the user:
http://myhost/chat/room/:roomId/message/:messageId
Body-parser is set like this:
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
I am unable to read the first url parameter :roomId but the :messageId is available.
I am accessing those parameters using req.params.roomId and req.params.messageId in request callback function.
Question:
Is it wrong to have parameters in the middle of a url?
Why would the application not parse :roomId?
The parameters roomId and so are send as query parameter therefore req.params.roomId is required to fetch.
Another way to do is send params as body, that way URL will be clean and then to access params body-parser is required.
To send params in body, create a post request through postman and specify params there.refer this for sending params in body
It is working in my case.
var app = require('express')();
var bodyParser= require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get('/chat/room/:roomId/message/:messageId', function(req, res){
console.log('Room Id: '+req.params.roomId);
console.log('Message Id: '+req.params.messageId);
res.sendStatus(200);
});
app.listen(3000);
Now, if I try to access localhost:3000/chat/room/1/message/100, I get
Room Id: 1
Message Id: 100
Please check the spelling of roomId. May be typo can be the issue.
Thank you for your answers Mukesh Sharma and Himani Agrawal.
I found the issue now, here it is:
If I register a room router like this:
var RoomRouter = express.Router();
RoomRouter.get('/:roomId/message/:messageId', function(req, res) {
console.log('Room Id: '+req.params.roomId);
console.log('Message Id: '+req.params.messageId);
res.status(200);
res.send("Ok");
});
app.use('/chat/room', RoomRouter);
:roomId and :messageId are received accordingly.
But if I register the room router like this (as it was when I posted the error) :roomId is not available.
var RoomRouter = express.Router();
RoomRouter.get('/message/:messageId', function(req, res) {
console.log('Room Id: '+req.params.roomId);
console.log('Message Id: '+req.params.messageId);
res.status(200);
res.send("Ok");
});
app.use('/chat/room/:roomId', RoomRouter);
This was my issue, I don't know exactly why the url would be parsed differently in two different situation but I am sure this has a logic somewhere.

Mailgun webhook POST body seems empty

I'am trying to handle http post message from Mailgun bounce webhook. When sending it to Mailgun's Postbin service all data is found of course. But I'm now sending that POST to my localhost server for development purposes and all I get is empty json array. I use Test Webhook.
Intent is to keep this simple as possible besides our main service. That for I started using nodejs/expressjs to create stand alone webservice to work as relay to receive POST messages of email bounces from Mailgun and inform admins about bounced email addresses.
Now I can't figure why I don't get the same data as is visible in Postbin.
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mailgun = require('mailgun-js')({apiKey: 'key-...', domain: 'mymailgundomain.com'});
app.use(bodyParser.urlencoded({
extended: true
}));
function router(app) {
app.post('/webhooks/*', function (req, res, next) {
var body = req.body;
if (!mailgun.validateWebhook(body.timestamp, body.token, body.signature)) {
console.error('Request came, but not from Mailgun');
res.send({ error: { message: 'Invalid signature. Are you even Mailgun?' } });
return;
}
next();
});
app.post('/webhooks/mailgun/', function (req, res) {
// actually handle request here
console.log("got post message");
res.send("ok 200");
});
}
app.listen(5000, function(){
router(app);
console.log("listening post in port 5000");
});
I'm running this from Mailgun's Test Webhook using url like http://mylocalhostwithpublicip.com:5000/webhooks/mailgun
Code structure is copied from https://github.com/1lobby/mailgun-js. Probably I'm missing something fundamental here as I can't figure it out myself.
The reason you're not seeing req.body populated is because the body-parser module does not support multipart/form-data requests. For those kinds of requests you need a different module such as multer, busboy/connect-busboy, multiparty, or formidable.
If your content-type (shown by logging console.dir(req.headers['content-type'])) is 'application/x-www-form-urlencoded', and you're using body-parser, try adding the following line:
bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
to make it work with multer, you can use .any() (version 1.1.0)
for me it worked like this: (assuming multer is included and declared as "multer")
post('/track', multer.any(),function(req, res){
//if body is a string, parse the json
var data=(typeof req.body=='string')?JSON.parse(req.body):req.body;
//if data is an object but you can't verify if a field exists with hasOwnProperty, force conversion with JSON
if(typeof data=='object' && typeof data.hasOwnProperty=='undefined')
data=JSON.parse(JSON.stringify(data));
//data is your object
});
var multer = require('multer');
var msg = multer();
post('/track', msg.any(), function(req, res){
console.log(req.body);
}
I make a custom parser for get data in req.body when the Content-type = 'multipart/alternative'
https://github.com/josemadev/Multiparser/

Resources