Nodejs: How can i simply get the request body using express4? - node.js

Now that express is not shipped anymore with middleware that fills the req.body variable i am fighting to get req.body filled again.
I am sending a POST request to /xyz/:object/feedback.
here my code:
app.post('/xyz/:object/feedback', function(req, res)
{
console.log('Feedback received.');
console.log('Body: ', req.body); // is not available :(
res.set('Content-Type', 'text/plain; charset=utf8');
res.send(result ? JSON.stringify(req.body) : err);
});
I tried to use body-parser already, but "Feedback received." never got logged to my console. So something seems to get stuck here:
var bodyParser = require('body-parser');
app.use(bodyParser);
How can i get req.body filled? (i need some working code)

The problem is that you pass the whole module to the use method not the required instance.
Instead of this:
app.use(bodyParser);
do
app.use(bodyParser());

You need to do app.use(bodyParser()).
bodyParser() will return a function with what to use. bodyParser on its own is an invalid function for Express.

Related

JSON comes in undefined, where is the data lost?

I am using postman to test a rest API I'm building for a project. I'm trying to send some data to a post method, but the data is getting lost somewhere between Postman and the endpoint.
I've tried tracing the data with console logs, but nothing comes out (req.body is undefined). I'm pretty sure the issue isn't with the endpoint or router, as the same error comes up in postman as in the console of my IDE, which means there's some sort of communication.
// json I'm putting into postman. validated with Jsonlint.com
{
"Name": "testN",
"file": "file1",
"Path": "/home/userf",
"userName": "user1"
}
// profileWrite.js
const dbProfileWrite = require('../...db-ProfileWrite');
const bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
// my post method
async function post(req, res, next) {
try {
console.log("attempting to parse data: " + req.body);
let profile = req.body;
console.log("data parsed, writing profiles");
profile= await dbProfileWrite.writeProfile(profile);
res.status(201).json(profile);
} catch (err) {
next(err);
}
}
module.exports.post = post;
UPDATE 7/15/19:I have recreated a microversion of my project that is having this issue on stackblitz. there's some sort of package error that I'm working on, but here's the link. I've recreated the methodology I'm using in my project with the router and all and looked at the example in the express docs. hopefully this helps isolate the issue.The data still comes in undefined when I post to this api through postman, so helpfully this much smaller view of the whole project helps.
Assuming you are using Express framework, by the look of the post function. You need to use a middlewear function to process request body using body-parser. Make sure you are using the correct parser in this case
app.use(bodyParser.json())
You don't need body-parser anymore it was put back in to the core of express in the form of express.json, simply use app.use(express.json()).
To access the body of your request use req.body, it should come with a object with the keys representing the json sent;
var app = express();
app.use(express.json());
async function post(req, res, next) {
try {
console.log("attempting to parse data: " + req.body);
let profile = req.body; // no need to use any functions to parse it
console.log("data parsed, writing profiles");
profile= await dbProfileWrite.writeProfile(profile);
res.status(201).json(profile);
console.log("profilecreated");
} catch (err) {
next(err);
}
}
See the express documentation
Solved the issue myself with a little help from John Schmitz. The issue was that I was defining the router and the server before actually telling it how to handle json bodies/ objects, so the body came through as the default undefined. In my index.js, the following is what fixed the code:
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use('/api/v1', router);
the key to this is that the app is told to use json and express.urlencoded before the router is declared. these actions have to happen in this order, and all before app.listen is called. once the app is listening, all of its params are set and you can't change them. Tl;dr: node is VERY picky, and you HAVE to define these things in the right place. thanks all for the help.

Web donĀ“t load when i use cookie-parser in NodeJS

I'm trying to get the value of a cookie with a cookie-parser.
The code is as follows (app.js):
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.get('/', function (req, res) {
console.log('Cookies: ', req.cookies);
});
The log shows the cookies and their value but the page shows the error ERR_EMPTY_RESPONSE
If I do not use this, the web loads perfectly.
I hope you can help me, thanks in advance.
Every middleware function must either invoke the next one in the chain to continue request processing, or finish the response by itself (using res.end() or res.send(...) or similar functions). In your case you're not passing control to next middleware, so response is ending with your function - but you're not properly ending the response either. That's why the error.
If you just want to print cookie value, you can invoke the next middleware in chain by using :
app.get('/', function (req, res, next) {
console.log('Cookies: ', req.cookies);
next(); //--> Added to call next middleware in chain
});
Do you have this at the bottom?
app.listen(8080)

Avoid global variables in Node, how to return the body of a request from a POST call

I'm still new to Node so I'm sure I'm doing something wrong, but some searching isn't helping so here we are.
I'm making a request to an API to get weather data. I can get the data and log it to the console no problem, but I'm having trouble getting the body of the request to end up in the response to the original POST.
var express = require('express');
var request = require('request');
var bodyParser = require('body-parser');
// create a new express server
var app = express();
// serve the files out of ./public as our main files
app.use(express.static(__dirname + '/public'));
// make the web server use body-parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// start server on the specified port and binding host
app.listen(appEnv.port, '0.0.0.0', function() {
console.log("server starting on " + appEnv.url);
});
// Send information from the weather API to the console
app.post('/processWeather', function (req, res) {
requestString = 'http://api.openweathermap.org/data/2.5/weather?id=7839805&appid=xxxxxxxx';
request(requestString, function(err, res, body){
if (!err && res.statusCode == 200) {
console.log(body);
}
});
//redirect back to homepage after getting the weather
res.redirect("/");
});
So the problem with this is that I can't simply use the body variable in the app.post callback. I'm suspicious this is to do asynchronous logic but I'm as I'm new I can't wrap my head around the best way to do this without using a global variable to temporarily store the body variable. How can I get the contents of the body variable sent back to the browser? Any help greatly appreciated. Cheers.
Don't use global variables unless it's absolutely necessary!
You can use session.
req.session['weather'] = weatherData; // Weather data
res.redirect("/");
You can use a lot of other ways also. But this is what I'd prefer.
I figured out what I needed. All I had to do was place the request in the res.send
res.send(request(requestString));

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