JSON comes in undefined, where is the data lost? - node.js

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.

Related

req.query undefined in Nuxt Express Middleware get request

Not a pro with things like server middleware, but stuck without much clues.
In a vue component I am retrieving data with axios with this:
axios
.get('/api/getDailyFeedback', {
params: {
start: '2018-05-01'
}
})
Which goes to the express (version 4.16.2) server middleware setup in Nuxt. I have gotten normal get and post requests to work fine but the problem is when I want to pass in a parameter into a get request like the below:
router.get('/getDailyFeedback', (req, res) => {
console.log('Query:', req.query.start);
//do stuff
});
What little experience I had with Express 4, it took me a little bit of time to realise why parameters passed in the body of a post request were undefined, but it was because I needed to add body-parser.json() to my nuxt config since they removed that from the main express package. Similarly I thought I needed bodyParse.urlencoded but that has not worked. This is the line I added to my nuxt.config:
serverMiddleware: [bodyParser.urlencoded({ extended: false }), bodyParser.json(), '~/api'],
I am unsure if the content type is not set correctly or I am missing something simple here. I know I am able to use various libraries to grab the parameters from the url string which I have access to, as Axios is working as expected and adding my 'params' object onto the end of my get request. But a lot of solutions I have seen to other problems is 'oh its as simple as accessing req.query' Alas Express fails to define a req.query object, or even req.params or req.body.
Hopefully that is enough detail to go on, thanks a lot for reading and any suggestions.
Well that's an unpleasant surprise to try to use the get request in Nuxt for the first time, isn't it? Nuxt creates a connect instance which leads to some pitfalls. It's req is the Node.js http request object, so it doesn't have the query property and request.body is also being skipped in get requests!
But there is a way for everything. Your code:
axios.get('/api/getDailyFeedback', {
params: {
start: '2018-05-01'
}
})
Translates to the following URI call:
/api/getDailyFeedback?start=2018-05-01
So you've got all the params in the URI where you can retrieve them from via url parsing. Module url ships with Node.js by the way.
const url = require("url");
router.get('/getDailyFeedback', (req, res) => {
let queryData = url.parse(req.url, true).query
console.log('Query:', queryData.start)
});
I wrote a little helper that extends req with a custom property. Here's the code:
router.use((req, res, next) => {
var theQuery = url.parse(req.url, true).query
req.queryData = theQuery
next()
})
Then you can use it like this:
router.get('/getDailyFeedback', (req, res) => {
console.log('Query:', req.queryData.start)
});
Other way to pass params via get is by using optional uri segments:
router.get('/getDailyFeedback/:start?', (req, res) => {
console.log('Query:', req.params.start)
});
I am using Nuxt 2.15 and I can access the query parameter like this req._parsedOriginalUrl.query
You can access Nuxt get params without additional modules.
Just use:
req.request.get()
For anyone else in the future
const { Router } = require('express')
Router.get('/orders', async (req, res, next) => {
const request = req.query.sometext;
res.json({data: request});
});
module.exports = Router;
<script>
export default() {
async mounted() {
const orders = await axios.get(`/api/orders`, {
params: {
sometext: 'bla bla'
}
});
}
}
</script>
http://expressjs.com/en/api.html#req

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

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/

Nodejs: How can i simply get the request body using express4?

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.

Accessing Post Parameters in NodeJS from an Angular $resource.save Call

I am using an AngularJS Resource to make an ajax post to a node js server running express. However I am unable to access the post payload parameters on the NodeJS side.
I have a service set up:
angular.module('app.services', ['ngResource'])
.factory('PostService', function($resource) {
return $resource('/postTest');
});
and in the controller I have:
function UserCtrl($scope, PostService) {
//query for the users
$scope.testPost = function() {
var stuff = {firstname: 'some', lastname:'person'};
PostService.save(stuff,function(data) {
console.log('called save on PostService');
});
};
}
I can see the payload inside of the http header:
{"firstname":"some","lastname":"person"}
however, when I get to the NodeJS route to process it, I am not sure how to access the parameters:
(output from node console): inside test stuff
req.params undefined
app.post('/postTest', function(req, res) {
console.log('inside test stuff');
console.log('req.params ' + req.param('stuff'));
})
I have created a fiddle at: http://jsfiddle.net/binarygiant/QNqRj/
Can anyone explain how to access the parameters passed by the post in my NodeJS route?
Thanks in advance
If "{"firstname":"some","lastname":"person"}" is in the body of the post in json?
You'd access it differently.
Using express.bodyParser(), req.body.firstname will get you the firstname
app.use(express.bodyParser());
Then
app.post('/postTest', function(req, res) {
console.log('inside test stuff');
console.log(req.body.firstname);
})
You need to set body parser in your App
for example in ExpressJs 4,
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

Resources